blob: acbc92439bfaa0355db467a52b5acc7f83b53a58 [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;
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +000089using webrtc::kSdpWithoutSdesAndDtlsDisabled;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090using webrtc::kSessionError;
91using webrtc::kSetLocalSdpFailed;
92using webrtc::kSetRemoteSdpFailed;
93using webrtc::kPushDownAnswerTDFailed;
94using webrtc::kPushDownPranswerTDFailed;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000095using webrtc::kBundleWithoutRtcpMux;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096
97static const SocketAddress kClientAddr1("11.11.11.11", 0);
98static const SocketAddress kClientAddr2("22.22.22.22", 0);
99static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
100
101static const char kSessionVersion[] = "1";
102
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103// Media index of candidates belonging to the first media content.
104static const int kMediaContentIndex0 = 0;
105static const char kMediaContentName0[] = "audio";
106
107// Media index of candidates belonging to the second media content.
108static const int kMediaContentIndex1 = 1;
109static const char kMediaContentName1[] = "video";
110
111static const int kIceCandidatesTimeout = 10000;
112
113static const cricket::AudioCodec
114 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
115static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
116static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
117
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000118static const char kFakeDtlsFingerprint[] =
119 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
120 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
121
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122// Add some extra |newlines| to the |message| after |line|.
123static void InjectAfter(const std::string& line,
124 const std::string& newlines,
125 std::string* message) {
126 const std::string tmp = line + newlines;
127 talk_base::replace_substrs(line.c_str(), line.length(),
128 tmp.c_str(), tmp.length(), message);
129}
130
131class MockIceObserver : public webrtc::IceObserver {
132 public:
133 MockIceObserver()
134 : oncandidatesready_(false),
135 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
136 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
137 }
138
139 virtual void OnIceConnectionChange(
140 PeerConnectionInterface::IceConnectionState new_state) {
141 ice_connection_state_ = new_state;
142 }
143 virtual void OnIceGatheringChange(
144 PeerConnectionInterface::IceGatheringState new_state) {
145 // We can never transition back to "new".
146 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
147 ice_gathering_state_ = new_state;
148
149 // oncandidatesready_ really means "ICE gathering is complete".
150 // This if statement ensures that this value remains correct when we
151 // transition from kIceGatheringComplete to kIceGatheringGathering.
152 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
153 oncandidatesready_ = false;
154 }
155 }
156
157 // Found a new candidate.
158 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
159 if (candidate->sdp_mline_index() == kMediaContentIndex0) {
160 mline_0_candidates_.push_back(candidate->candidate());
161 } else if (candidate->sdp_mline_index() == kMediaContentIndex1) {
162 mline_1_candidates_.push_back(candidate->candidate());
163 }
164 // The ICE gathering state should always be Gathering when a candidate is
165 // received (or possibly Completed in the case of the final candidate).
166 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
167 }
168
169 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
170 virtual void OnIceComplete() {
171 EXPECT_FALSE(oncandidatesready_);
172 oncandidatesready_ = true;
173
174 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
175 // be called approximately simultaneously. For ease of testing, this
176 // check additionally requires that they be called in the above order.
177 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
178 ice_gathering_state_);
179 }
180
181 bool oncandidatesready_;
182 std::vector<cricket::Candidate> mline_0_candidates_;
183 std::vector<cricket::Candidate> mline_1_candidates_;
184 PeerConnectionInterface::IceConnectionState ice_connection_state_;
185 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
186};
187
188class WebRtcSessionForTest : public webrtc::WebRtcSession {
189 public:
190 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
191 talk_base::Thread* signaling_thread,
192 talk_base::Thread* worker_thread,
193 cricket::PortAllocator* port_allocator,
194 webrtc::IceObserver* ice_observer,
195 webrtc::MediaStreamSignaling* mediastream_signaling)
196 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
197 mediastream_signaling) {
198 RegisterIceObserver(ice_observer);
199 }
200 virtual ~WebRtcSessionForTest() {}
201
202 using cricket::BaseSession::GetTransportProxy;
203 using webrtc::WebRtcSession::SetAudioPlayout;
204 using webrtc::WebRtcSession::SetAudioSend;
205 using webrtc::WebRtcSession::SetCaptureDevice;
206 using webrtc::WebRtcSession::SetVideoPlayout;
207 using webrtc::WebRtcSession::SetVideoSend;
208};
209
wu@webrtc.org91053e72013-08-10 07:18:04 +0000210class WebRtcSessionCreateSDPObserverForTest
211 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000213 enum State {
214 kInit,
215 kFailed,
216 kSucceeded,
217 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000218 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000219
220 // CreateSessionDescriptionObserver implementation.
221 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000222 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000223 state_ = kSucceeded;
224 }
225 virtual void OnFailure(const std::string& error) {
226 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 }
228
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000229 SessionDescriptionInterface* description() { return description_.get(); }
230
231 SessionDescriptionInterface* ReleaseDescription() {
232 return description_.release();
233 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234
wu@webrtc.org91053e72013-08-10 07:18:04 +0000235 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000236
wu@webrtc.org91053e72013-08-10 07:18:04 +0000237 protected:
238 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239
240 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000241 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000242 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243};
244
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000245class FakeAudioRenderer : public cricket::AudioRenderer {
246 public:
247 FakeAudioRenderer() : channel_id_(-1) {}
248
249 virtual void AddChannel(int channel_id) OVERRIDE {
250 ASSERT(channel_id_ == -1);
251 channel_id_ = channel_id;
252 }
253 virtual void RemoveChannel(int channel_id) OVERRIDE {
254 ASSERT(channel_id == channel_id_);
255 channel_id_ = -1;
256 }
257
258 int channel_id() const { return channel_id_; }
259 private:
260 int channel_id_;
261};
262
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000263class WebRtcSessionTest : public testing::Test {
264 protected:
265 // TODO Investigate why ChannelManager crashes, if it's created
266 // after stun_server.
267 WebRtcSessionTest()
268 : media_engine_(new cricket::FakeMediaEngine()),
269 data_engine_(new cricket::FakeDataEngine()),
270 device_manager_(new cricket::FakeDeviceManager()),
271 channel_manager_(new cricket::ChannelManager(
272 media_engine_, data_engine_, device_manager_,
273 new cricket::CaptureManager(), talk_base::Thread::Current())),
274 tdesc_factory_(new cricket::TransportDescriptionFactory()),
275 desc_factory_(new cricket::MediaSessionDescriptionFactory(
276 channel_manager_.get(), tdesc_factory_.get())),
277 pss_(new talk_base::PhysicalSocketServer),
278 vss_(new talk_base::VirtualSocketServer(pss_.get())),
279 fss_(new talk_base::FirewallSocketServer(vss_.get())),
280 ss_scope_(fss_.get()),
281 stun_server_(talk_base::Thread::Current(), kStunAddr),
282 allocator_(&network_manager_, kStunAddr,
wu@webrtc.org967bfff2013-09-19 05:49:50 +0000283 SocketAddress(), SocketAddress(), SocketAddress()),
284 mediastream_signaling_(channel_manager_.get()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
286 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
287 cricket::PORTALLOCATOR_DISABLE_RELAY |
288 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
289 EXPECT_TRUE(channel_manager_->Init());
290 desc_factory_->set_add_legacy_streams(false);
291 }
292
293 void AddInterface(const SocketAddress& addr) {
294 network_manager_.AddInterface(addr);
295 }
296
wu@webrtc.org91053e72013-08-10 07:18:04 +0000297 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000298 ASSERT_TRUE(session_.get() == NULL);
299 session_.reset(new WebRtcSessionForTest(
300 channel_manager_.get(), talk_base::Thread::Current(),
301 talk_base::Thread::Current(), &allocator_,
302 &observer_,
303 &mediastream_signaling_));
304
305 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
306 observer_.ice_connection_state_);
307 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
308 observer_.ice_gathering_state_);
309
wu@webrtc.org91053e72013-08-10 07:18:04 +0000310 EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 }
312
313 void InitWithDtmfCodec() {
314 // Add kTelephoneEventCodec for dtmf test.
315 std::vector<cricket::AudioCodec> codecs;
316 codecs.push_back(kTelephoneEventCodec);
317 media_engine_->SetAudioCodecs(codecs);
318 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000319 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320 }
321
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000322 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000323 FakeIdentityService* identity_service = new FakeIdentityService();
324 identity_service->set_should_fail(identity_request_should_fail);
325 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 }
327
328 // Creates a local offer and applies it. Starts ice.
329 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
330 // to decide which streams to create.
331 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000332 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000333 SetLocalDescriptionWithoutError(offer);
334 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
335 observer_.ice_gathering_state_,
336 kIceCandidatesTimeout);
337 }
338
wu@webrtc.org91053e72013-08-10 07:18:04 +0000339 SessionDescriptionInterface* CreateOffer(
340 const webrtc::MediaConstraintsInterface* constraints) {
341 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
342 observer = new WebRtcSessionCreateSDPObserverForTest();
343 session_->CreateOffer(observer, constraints);
344 EXPECT_TRUE_WAIT(
345 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000346 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000347 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000348 }
349
350 SessionDescriptionInterface* CreateAnswer(
351 const webrtc::MediaConstraintsInterface* constraints) {
352 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
353 = new WebRtcSessionCreateSDPObserverForTest();
354 session_->CreateAnswer(observer, constraints);
355 EXPECT_TRUE_WAIT(
356 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000357 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000358 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000359 }
360
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000361 bool ChannelsExist() {
362 return (session_->voice_channel() != NULL &&
363 session_->video_channel() != NULL);
364 }
365
366 void CheckTransportChannels() {
367 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
368 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
369 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
370 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
371 }
372
373 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
374 ASSERT_TRUE(session_.get() != NULL);
375 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
376 ASSERT_TRUE(content != NULL);
377 const cricket::AudioContentDescription* audio_content =
378 static_cast<const cricket::AudioContentDescription*>(
379 content->description);
380 ASSERT_TRUE(audio_content != NULL);
381 ASSERT_EQ(1U, audio_content->cryptos().size());
382 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
383 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
384 audio_content->cryptos()[0].cipher_suite);
385 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
386 audio_content->protocol());
387
388 content = cricket::GetFirstVideoContent(sdp);
389 ASSERT_TRUE(content != NULL);
390 const cricket::VideoContentDescription* video_content =
391 static_cast<const cricket::VideoContentDescription*>(
392 content->description);
393 ASSERT_TRUE(video_content != NULL);
394 ASSERT_EQ(1U, video_content->cryptos().size());
395 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
396 video_content->cryptos()[0].cipher_suite);
397 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
398 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
399 video_content->protocol());
400 }
401
402 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
403 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
404 ASSERT_TRUE(content != NULL);
405 const cricket::AudioContentDescription* audio_content =
406 static_cast<const cricket::AudioContentDescription*>(
407 content->description);
408 ASSERT_TRUE(audio_content != NULL);
409 ASSERT_EQ(0U, audio_content->cryptos().size());
410
411 content = cricket::GetFirstVideoContent(sdp);
412 ASSERT_TRUE(content != NULL);
413 const cricket::VideoContentDescription* video_content =
414 static_cast<const cricket::VideoContentDescription*>(
415 content->description);
416 ASSERT_TRUE(video_content != NULL);
417 ASSERT_EQ(0U, video_content->cryptos().size());
418
419 if (dtls) {
420 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
421 audio_content->protocol());
422 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
423 video_content->protocol());
424 } else {
425 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
426 audio_content->protocol());
427 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
428 video_content->protocol());
429 }
430 }
431
432 // Set the internal fake description factories to do DTLS-SRTP.
433 void SetFactoryDtlsSrtp() {
434 desc_factory_->set_secure(cricket::SEC_ENABLED);
435 std::string identity_name = "WebRTC" +
436 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000437 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
438 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000439 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
440 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
441 }
442
443 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
444 bool expected) {
445 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
446 ASSERT_TRUE(audio != NULL);
447 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
448 if (expected) {
449 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
450 identity_fingerprint->algorithm);
451 }
452 const TransportInfo* video = sdp->GetTransportInfoByName("video");
453 ASSERT_TRUE(video != NULL);
454 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
455 if (expected) {
456 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
457 identity_fingerprint->algorithm);
458 }
459 }
460
461 void VerifyAnswerFromNonCryptoOffer() {
462 // Create a SDP without Crypto.
463 cricket::MediaSessionOptions options;
464 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000465 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000466 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000467 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 VerifyNoCryptoParams(offer->description(), false);
469 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
wu@webrtc.org91053e72013-08-10 07:18:04 +0000470 offer);
471 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000472 // Answer should be NULL as no crypto params in offer.
473 ASSERT_TRUE(answer == NULL);
474 }
475
476 void VerifyAnswerFromCryptoOffer() {
477 cricket::MediaSessionOptions options;
478 options.has_video = true;
479 options.bundle_enabled = true;
480 scoped_ptr<JsepSessionDescription> offer(
481 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
482 ASSERT_TRUE(offer.get() != NULL);
483 VerifyCryptoParams(offer->description());
484 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000485 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 ASSERT_TRUE(answer.get() != NULL);
487 VerifyCryptoParams(answer->description());
488 }
489
490 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
491 const cricket::SessionDescription* desc2,
492 bool expect_equal) {
493 if (desc1->contents().size() != desc2->contents().size()) {
494 EXPECT_FALSE(expect_equal);
495 return;
496 }
497
498 const cricket::ContentInfos& contents = desc1->contents();
499 cricket::ContentInfos::const_iterator it = contents.begin();
500
501 for (; it != contents.end(); ++it) {
502 const cricket::TransportDescription* transport_desc1 =
503 desc1->GetTransportDescriptionByName(it->name);
504 const cricket::TransportDescription* transport_desc2 =
505 desc2->GetTransportDescriptionByName(it->name);
506 if (!transport_desc1 || !transport_desc2) {
507 EXPECT_FALSE(expect_equal);
508 return;
509 }
510 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
511 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
512 EXPECT_FALSE(expect_equal);
513 return;
514 }
515 }
516 EXPECT_TRUE(expect_equal);
517 }
518 // Creates a remote offer and and applies it as a remote description,
519 // creates a local answer and applies is as a local description.
520 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
521 // to decide which local and remote streams to create.
522 void CreateAndSetRemoteOfferAndLocalAnswer() {
523 SessionDescriptionInterface* offer = CreateRemoteOffer();
524 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000525 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526 SetLocalDescriptionWithoutError(answer);
527 }
528 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
529 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
530 }
531 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
532 BaseSession::State expected_state) {
533 SetLocalDescriptionWithoutError(desc);
534 EXPECT_EQ(expected_state, session_->state());
535 }
536 void SetLocalDescriptionExpectError(const std::string& expected_error,
537 SessionDescriptionInterface* desc) {
538 std::string error;
539 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
540 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
541 EXPECT_NE(std::string::npos, error.find(expected_error));
542 }
543 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
544 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
545 }
546 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
547 BaseSession::State expected_state) {
548 SetRemoteDescriptionWithoutError(desc);
549 EXPECT_EQ(expected_state, session_->state());
550 }
551 void SetRemoteDescriptionExpectError(const std::string& expected_error,
552 SessionDescriptionInterface* desc) {
553 std::string error;
554 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
555 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
556 EXPECT_NE(std::string::npos, error.find(expected_error));
557 }
558
559 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
560 SessionDescriptionInterface** nocrypto_answer) {
561 // Create a SDP without Crypto.
562 cricket::MediaSessionOptions options;
563 options.has_video = true;
564 options.bundle_enabled = true;
565 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
566 ASSERT_TRUE(*offer != NULL);
567 VerifyCryptoParams((*offer)->description());
568
569 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
570 cricket::SEC_DISABLED);
571 EXPECT_TRUE(*nocrypto_answer != NULL);
572 }
573
574 JsepSessionDescription* CreateRemoteOfferWithVersion(
575 cricket::MediaSessionOptions options,
576 cricket::SecurePolicy secure_policy,
577 const std::string& session_version,
578 const SessionDescriptionInterface* current_desc) {
579 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
580 const cricket::SessionDescription* cricket_desc = NULL;
581 if (current_desc) {
582 cricket_desc = current_desc->description();
583 session_id = current_desc->session_id();
584 }
585
586 desc_factory_->set_secure(secure_policy);
587 JsepSessionDescription* offer(
588 new JsepSessionDescription(JsepSessionDescription::kOffer));
589 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
590 session_id, session_version)) {
591 delete offer;
592 offer = NULL;
593 }
594 return offer;
595 }
596 JsepSessionDescription* CreateRemoteOffer(
597 cricket::MediaSessionOptions options) {
598 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
599 kSessionVersion, NULL);
600 }
601 JsepSessionDescription* CreateRemoteOffer(
602 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
603 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
604 }
605 JsepSessionDescription* CreateRemoteOffer(
606 cricket::MediaSessionOptions options,
607 const SessionDescriptionInterface* current_desc) {
608 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
609 kSessionVersion, current_desc);
610 }
611
612 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
613 // before this function to decide which streams to create.
614 JsepSessionDescription* CreateRemoteOffer() {
615 cricket::MediaSessionOptions options;
616 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
617 return CreateRemoteOffer(options, session_->remote_description());
618 }
619
620 JsepSessionDescription* CreateRemoteAnswer(
621 const SessionDescriptionInterface* offer,
622 cricket::MediaSessionOptions options,
623 cricket::SecurePolicy policy) {
624 desc_factory_->set_secure(policy);
625 const std::string session_id =
626 talk_base::ToString(talk_base::CreateRandomId64());
627 JsepSessionDescription* answer(
628 new JsepSessionDescription(JsepSessionDescription::kAnswer));
629 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
630 options, NULL),
631 session_id, kSessionVersion)) {
632 delete answer;
633 answer = NULL;
634 }
635 return answer;
636 }
637
638 JsepSessionDescription* CreateRemoteAnswer(
639 const SessionDescriptionInterface* offer,
640 cricket::MediaSessionOptions options) {
641 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
642 }
643
644 // Creates an answer session description with streams based on
645 // |mediastream_signaling_|. Call
646 // mediastream_signaling_.UseOptionsWithStreamX() before this function
647 // to decide which streams to create.
648 JsepSessionDescription* CreateRemoteAnswer(
649 const SessionDescriptionInterface* offer) {
650 cricket::MediaSessionOptions options;
651 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
652 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
653 }
654
655 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
656 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000657 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 mediastream_signaling_.SendAudioVideoStream1();
659 FakeConstraints constraints;
660 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000661 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
663 // and answer.
664 SetLocalDescriptionWithoutError(offer);
665
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000666 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
667 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 std::string sdp;
669 EXPECT_TRUE(answer->ToString(&sdp));
670
671 size_t expected_candidate_num = 2;
672 if (!rtcp_mux) {
673 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
674 // for rtp and rtcp.
675 expected_candidate_num = 4;
676 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 const std::string kRtcpMux = "a=rtcp-mux";
678 const std::string kXRtcpMux = "a=xrtcp-mux";
679 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
680 kXRtcpMux.c_str(), kXRtcpMux.length(),
681 &sdp);
682 }
683
684 SessionDescriptionInterface* new_answer = CreateSessionDescription(
685 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686
687 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000688 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
690 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
691 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
692 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
693 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
694 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
695 if (bundle) {
696 EXPECT_TRUE(c0.IsEquivalent(c1));
697 } else {
698 EXPECT_FALSE(c0.IsEquivalent(c1));
699 }
700 }
701 }
702 // Tests that we can only send DTMF when the dtmf codec is supported.
703 void TestCanInsertDtmf(bool can) {
704 if (can) {
705 InitWithDtmfCodec();
706 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000707 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 }
709 mediastream_signaling_.SendAudioVideoStream1();
710 CreateAndSetRemoteOfferAndLocalAnswer();
711 EXPECT_FALSE(session_->CanInsertDtmf(""));
712 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
713 }
714
715 // The method sets up a call from the session to itself, in a loopback
716 // arrangement. It also uses a firewall rule to create a temporary
717 // disconnection. This code is placed as a method so that it can be invoked
718 // by multiple tests with different allocators (e.g. with and without BUNDLE).
719 // While running the call, this method also checks if the session goes through
720 // the correct sequence of ICE states when a connection is established,
721 // broken, and re-established.
722 // The Connection state should go:
723 // New -> Checking -> Connected -> Disconnected -> Connected.
724 // The Gathering state should go: New -> Gathering -> Completed.
725 void TestLoopbackCall() {
726 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000727 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000729 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730
731 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
732 observer_.ice_gathering_state_);
733 SetLocalDescriptionWithoutError(offer);
734 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
735 observer_.ice_connection_state_);
736 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
737 observer_.ice_gathering_state_,
738 kIceCandidatesTimeout);
739 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
740 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
741 observer_.ice_gathering_state_,
742 kIceCandidatesTimeout);
743
744 std::string sdp;
745 offer->ToString(&sdp);
746 SessionDescriptionInterface* desc =
747 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
748 ASSERT_TRUE(desc != NULL);
749 SetRemoteDescriptionWithoutError(desc);
750
751 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
752 observer_.ice_connection_state_,
753 kIceCandidatesTimeout);
754 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
755 observer_.ice_connection_state_,
756 kIceCandidatesTimeout);
757 // TODO(bemasc): EXPECT(Completed) once the details are standardized.
758
759 // Adding firewall rule to block ping requests, which should cause
760 // transport channel failure.
761 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
762 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
763 observer_.ice_connection_state_,
764 kIceCandidatesTimeout);
765
766 // Clearing the rules, session should move back to completed state.
767 fss_->ClearRules();
768 // Session is automatically calling OnSignalingReady after creation of
769 // new portallocator session which will allocate new set of candidates.
770
771 // TODO(bemasc): Change this to Completed once the details are standardized.
772 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
773 observer_.ice_connection_state_,
774 kIceCandidatesTimeout);
775 }
776
777 void VerifyTransportType(const std::string& content_name,
778 cricket::TransportProtocol protocol) {
779 const cricket::Transport* transport = session_->GetTransport(content_name);
780 ASSERT_TRUE(transport != NULL);
781 EXPECT_EQ(protocol, transport->protocol());
782 }
783
784 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
785 void AddCNCodecs() {
786 // Add kTelephoneEventCodec for dtmf test.
787 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
788 codecs.push_back(kCNCodec1);
789 codecs.push_back(kCNCodec2);
790 media_engine_->SetAudioCodecs(codecs);
791 desc_factory_->set_audio_codecs(codecs);
792 }
793
794 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
795 const cricket::ContentDescription* description = content->description;
796 ASSERT(description != NULL);
797 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000798 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000799 ASSERT(audio_content_desc != NULL);
800 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
801 if (audio_content_desc->codecs()[i].name == "CN")
802 return false;
803 }
804 return true;
805 }
806
807 void SetLocalDescriptionWithDataChannel() {
808 webrtc::DataChannelInit dci;
809 dci.reliable = false;
810 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000811 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000812 SetLocalDescriptionWithoutError(offer);
813 }
814
wu@webrtc.org91053e72013-08-10 07:18:04 +0000815 void VerifyMultipleAsyncCreateDescription(
816 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000817 InitWithDtls(!success);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000818
819 if (type == CreateSessionDescriptionRequest::kAnswer) {
820 cricket::MediaSessionOptions options;
821 scoped_ptr<JsepSessionDescription> offer(
822 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
823 ASSERT_TRUE(offer.get() != NULL);
824 SetRemoteDescriptionWithoutError(offer.release());
825 }
826
827 const int kNumber = 3;
828 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
829 observers[kNumber];
830 for (int i = 0; i < kNumber; ++i) {
831 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
832 if (type == CreateSessionDescriptionRequest::kOffer) {
833 session_->CreateOffer(observers[i], NULL);
834 } else {
835 session_->CreateAnswer(observers[i], NULL);
836 }
837 }
838
839 WebRtcSessionCreateSDPObserverForTest::State expected_state =
840 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
841 WebRtcSessionCreateSDPObserverForTest::kFailed;
842
843 for (int i = 0; i < kNumber; ++i) {
844 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
845 if (success) {
846 EXPECT_TRUE(observers[i]->description() != NULL);
847 } else {
848 EXPECT_TRUE(observers[i]->description() == NULL);
849 }
850 }
851 }
852
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000853 cricket::FakeMediaEngine* media_engine_;
854 cricket::FakeDataEngine* data_engine_;
855 cricket::FakeDeviceManager* device_manager_;
856 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
857 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000858 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
860 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
861 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
862 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
863 talk_base::SocketServerScope ss_scope_;
864 cricket::TestStunServer stun_server_;
865 talk_base::FakeNetworkManager network_manager_;
866 cricket::BasicPortAllocator allocator_;
867 talk_base::scoped_ptr<FakeConstraints> constraints_;
868 FakeMediaStreamSignaling mediastream_signaling_;
869 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
870 MockIceObserver observer_;
871 cricket::FakeVideoMediaChannel* video_channel_;
872 cricket::FakeVoiceMediaChannel* voice_channel_;
873};
874
875TEST_F(WebRtcSessionTest, TestInitialize) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000876 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877}
878
879TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
880 InitWithDtls();
881}
882
wu@webrtc.org91053e72013-08-10 07:18:04 +0000883// Verifies that WebRtcSession uses SEC_REQUIRED by default.
884TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
885 Init(NULL);
886 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
887}
888
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000889TEST_F(WebRtcSessionTest, TestSessionCandidates) {
890 TestSessionCandidatesWithBundleRtcpMux(false, false);
891}
892
893// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
894// with rtcp-mux and/or bundle.
895TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
896 TestSessionCandidatesWithBundleRtcpMux(false, true);
897}
898
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000899TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
900 TestSessionCandidatesWithBundleRtcpMux(true, true);
901}
902
903TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
904 AddInterface(kClientAddr1);
905 AddInterface(kClientAddr2);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000906 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 mediastream_signaling_.SendAudioVideoStream1();
908 InitiateCall();
909 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
910 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
911 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
912}
913
914TEST_F(WebRtcSessionTest, TestStunError) {
915 AddInterface(kClientAddr1);
916 AddInterface(kClientAddr2);
917 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000918 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000919 mediastream_signaling_.SendAudioVideoStream1();
920 InitiateCall();
921 // Since kClientAddr1 is blocked, not expecting stun candidates for it.
922 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
923 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
924 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
925}
926
927// Test creating offers and receive answers and make sure the
928// media engine creates the expected send and receive streams.
929TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000930 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000931 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000932 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 const std::string session_id_orig = offer->session_id();
934 const std::string session_version_orig = offer->session_version();
935 SetLocalDescriptionWithoutError(offer);
936
937 mediastream_signaling_.SendAudioVideoStream2();
938 SessionDescriptionInterface* answer =
939 CreateRemoteAnswer(session_->local_description());
940 SetRemoteDescriptionWithoutError(answer);
941
942 video_channel_ = media_engine_->GetVideoChannel(0);
943 voice_channel_ = media_engine_->GetVoiceChannel(0);
944
945 ASSERT_EQ(1u, video_channel_->recv_streams().size());
946 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
947
948 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
949 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
950
951 ASSERT_EQ(1u, video_channel_->send_streams().size());
952 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
953 ASSERT_EQ(1u, voice_channel_->send_streams().size());
954 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
955
956 // Create new offer without send streams.
957 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000958 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959
960 // Verify the session id is the same and the session version is
961 // increased.
962 EXPECT_EQ(session_id_orig, offer->session_id());
963 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
964 talk_base::FromString<uint64>(offer->session_version()));
965
966 SetLocalDescriptionWithoutError(offer);
967
968 mediastream_signaling_.SendAudioVideoStream2();
969 answer = CreateRemoteAnswer(session_->local_description());
970 SetRemoteDescriptionWithoutError(answer);
971
972 EXPECT_EQ(0u, video_channel_->send_streams().size());
973 EXPECT_EQ(0u, voice_channel_->send_streams().size());
974
975 // Make sure the receive streams have not changed.
976 ASSERT_EQ(1u, video_channel_->recv_streams().size());
977 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
978 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
979 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
980}
981
982// Test receiving offers and creating answers and make sure the
983// media engine creates the expected send and receive streams.
984TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000985 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000987 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988 SetRemoteDescriptionWithoutError(offer);
989
990 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000991 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 SetLocalDescriptionWithoutError(answer);
993
994 const std::string session_id_orig = answer->session_id();
995 const std::string session_version_orig = answer->session_version();
996
997 video_channel_ = media_engine_->GetVideoChannel(0);
998 voice_channel_ = media_engine_->GetVoiceChannel(0);
999
1000 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1001 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1002
1003 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1004 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1005
1006 ASSERT_EQ(1u, video_channel_->send_streams().size());
1007 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1008 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1009 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1010
1011 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001012 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013 SetRemoteDescriptionWithoutError(offer);
1014
1015 // Answer by turning off all send streams.
1016 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001017 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018
1019 // Verify the session id is the same and the session version is
1020 // increased.
1021 EXPECT_EQ(session_id_orig, answer->session_id());
1022 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1023 talk_base::FromString<uint64>(answer->session_version()));
1024 SetLocalDescriptionWithoutError(answer);
1025
1026 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1027 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1028 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1029 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1030 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1031 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1032
1033 // Make sure we have no send streams.
1034 EXPECT_EQ(0u, video_channel_->send_streams().size());
1035 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1036}
1037
1038// Test we will return fail when apply an offer that doesn't have
1039// crypto enabled.
1040TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001041 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001042 cricket::MediaSessionOptions options;
1043 options.has_video = true;
1044 JsepSessionDescription* offer = CreateRemoteOffer(
1045 options, cricket::SEC_DISABLED);
1046 ASSERT_TRUE(offer != NULL);
1047 VerifyNoCryptoParams(offer->description(), false);
1048 // SetRemoteDescription and SetLocalDescription will take the ownership of
1049 // the offer.
1050 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
1051 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1052 ASSERT_TRUE(offer != NULL);
1053 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
1054}
1055
1056// Test we will return fail when apply an answer that doesn't have
1057// crypto enabled.
1058TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001059 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 SessionDescriptionInterface* offer = NULL;
1061 SessionDescriptionInterface* answer = NULL;
1062 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1063 // SetRemoteDescription and SetLocalDescription will take the ownership of
1064 // the offer.
1065 SetRemoteDescriptionWithoutError(offer);
1066 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
1067}
1068
1069// Test we will return fail when apply an answer that doesn't have
1070// crypto enabled.
1071TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001072 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001073 SessionDescriptionInterface* offer = NULL;
1074 SessionDescriptionInterface* answer = NULL;
1075 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1076 // SetRemoteDescription and SetLocalDescription will take the ownership of
1077 // the offer.
1078 SetLocalDescriptionWithoutError(offer);
1079 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
1080}
1081
1082// Test that we can create and set an offer with a DTLS fingerprint.
1083TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1084 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1085 InitWithDtls();
1086 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001087 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001088 ASSERT_TRUE(offer != NULL);
1089 VerifyFingerprintStatus(offer->description(), true);
1090 // SetLocalDescription will take the ownership of the offer.
1091 SetLocalDescriptionWithoutError(offer);
1092}
1093
1094// Test that we can process an offer with a DTLS fingerprint
1095// and that we return an answer with a fingerprint.
1096TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1097 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1098 InitWithDtls();
1099 SetFactoryDtlsSrtp();
1100 cricket::MediaSessionOptions options;
1101 options.has_video = true;
1102 JsepSessionDescription* offer = CreateRemoteOffer(options);
1103 ASSERT_TRUE(offer != NULL);
1104 VerifyFingerprintStatus(offer->description(), true);
1105
1106 // SetRemoteDescription will take the ownership of the offer.
1107 SetRemoteDescriptionWithoutError(offer);
1108
1109 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001110 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001111 ASSERT_TRUE(answer != NULL);
1112 VerifyFingerprintStatus(answer->description(), true);
1113 // Check that we don't have an a=crypto line in the answer.
1114 VerifyNoCryptoParams(answer->description(), true);
1115
1116 // Now set the local description, which should work, even without a=crypto.
1117 SetLocalDescriptionWithoutError(answer);
1118}
1119
1120// Test that even if we support DTLS, if the other side didn't offer a
1121// fingerprint, we don't either.
1122TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1123 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1124 InitWithDtls();
1125 cricket::MediaSessionOptions options;
1126 options.has_video = true;
1127 JsepSessionDescription* offer = CreateRemoteOffer(
1128 options, cricket::SEC_REQUIRED);
1129 ASSERT_TRUE(offer != NULL);
1130 VerifyFingerprintStatus(offer->description(), false);
1131
1132 // SetRemoteDescription will take the ownership of
1133 // the offer.
1134 SetRemoteDescriptionWithoutError(offer);
1135
1136 // Verify that we don't get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001137 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001138 ASSERT_TRUE(answer != NULL);
1139 VerifyFingerprintStatus(answer->description(), false);
1140
1141 // Now set the local description.
1142 SetLocalDescriptionWithoutError(answer);
1143}
1144
1145TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001146 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001147 mediastream_signaling_.SendNothing();
1148 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001149 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001150 SetLocalDescriptionWithoutError(offer);
1151
1152 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001153 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 SetLocalDescriptionWithoutError(offer2);
1155}
1156
1157TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001158 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001159 mediastream_signaling_.SendNothing();
1160 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001161 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001162 SetRemoteDescriptionWithoutError(offer);
1163
wu@webrtc.org91053e72013-08-10 07:18:04 +00001164 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 SetRemoteDescriptionWithoutError(offer2);
1166}
1167
1168TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001169 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001171 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001173 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174 SetRemoteDescriptionExpectError(
1175 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
1176 offer);
1177}
1178
1179TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001180 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001181 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001182 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001184 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 SetLocalDescriptionExpectError(
1186 "Called with type in wrong state, type: "
1187 "offer state: STATE_RECEIVEDINITIATE",
1188 offer);
1189}
1190
1191TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001192 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193 mediastream_signaling_.SendNothing();
1194 SessionDescriptionInterface* offer = CreateRemoteOffer();
1195 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1196
1197 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001198 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1200 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1201
1202 mediastream_signaling_.SendAudioVideoStream1();
1203 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001204 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001205 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1206
1207 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1208
1209 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001210 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001211 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1212}
1213
1214TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001215 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001217 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1219
1220 JsepSessionDescription* pranswer =
1221 CreateRemoteAnswer(session_->local_description());
1222 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1223
1224 SetRemoteDescriptionExpectState(pranswer,
1225 BaseSession::STATE_RECEIVEDPRACCEPT);
1226
1227 mediastream_signaling_.SendAudioVideoStream1();
1228 JsepSessionDescription* pranswer2 =
1229 CreateRemoteAnswer(session_->local_description());
1230 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1231
1232 SetRemoteDescriptionExpectState(pranswer2,
1233 BaseSession::STATE_RECEIVEDPRACCEPT);
1234
1235 mediastream_signaling_.SendAudioVideoStream2();
1236 SessionDescriptionInterface* answer =
1237 CreateRemoteAnswer(session_->local_description());
1238 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1239}
1240
1241TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001242 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243 mediastream_signaling_.SendNothing();
1244 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001245 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 SessionDescriptionInterface* answer =
1247 CreateRemoteAnswer(offer.get());
1248 SetLocalDescriptionExpectError(
1249 "Called with type in wrong state, type: answer state: STATE_INIT",
1250 answer);
1251}
1252
1253TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001254 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255 mediastream_signaling_.SendNothing();
1256 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001257 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001258 SessionDescriptionInterface* answer =
1259 CreateRemoteAnswer(offer.get());
1260 SetRemoteDescriptionExpectError(
1261 "Called with type in wrong state, type: answer state: STATE_INIT",
1262 answer);
1263}
1264
1265TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001266 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 mediastream_signaling_.SendAudioVideoStream1();
1268
1269 cricket::Candidate candidate;
1270 candidate.set_component(1);
1271 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1272
1273 // Fail since we have not set a offer description.
1274 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1275
wu@webrtc.org91053e72013-08-10 07:18:04 +00001276 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001277 SetLocalDescriptionWithoutError(offer);
1278 // Candidate should be allowed to add before remote description.
1279 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1280 candidate.set_component(2);
1281 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1282 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1283
1284 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1285 session_->local_description());
1286 SetRemoteDescriptionWithoutError(answer);
1287
1288 // Verifying the candidates are copied properly from internal vector.
1289 const SessionDescriptionInterface* remote_desc =
1290 session_->remote_description();
1291 ASSERT_TRUE(remote_desc != NULL);
1292 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1293 const IceCandidateCollection* candidates =
1294 remote_desc->candidates(kMediaContentIndex0);
1295 ASSERT_EQ(2u, candidates->count());
1296 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1297 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1298 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1299 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1300
1301 candidate.set_component(2);
1302 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1303 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1304 ASSERT_EQ(3u, candidates->count());
1305
1306 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1307 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1308}
1309
1310// Test that a remote candidate is added to the remote session description and
1311// that it is retained if the remote session description is changed.
1312TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001313 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 cricket::Candidate candidate1;
1315 candidate1.set_component(1);
1316 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1317 candidate1);
1318 mediastream_signaling_.SendAudioVideoStream1();
1319 CreateAndSetRemoteOfferAndLocalAnswer();
1320
1321 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1322 const SessionDescriptionInterface* remote_desc =
1323 session_->remote_description();
1324 ASSERT_TRUE(remote_desc != NULL);
1325 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1326 const IceCandidateCollection* candidates =
1327 remote_desc->candidates(kMediaContentIndex0);
1328 ASSERT_EQ(1u, candidates->count());
1329 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1330
1331 // Update the RemoteSessionDescription with a new session description and
1332 // a candidate and check that the new remote session description contains both
1333 // candidates.
1334 SessionDescriptionInterface* offer = CreateRemoteOffer();
1335 cricket::Candidate candidate2;
1336 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1337 candidate2);
1338 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1339 SetRemoteDescriptionWithoutError(offer);
1340
1341 remote_desc = session_->remote_description();
1342 ASSERT_TRUE(remote_desc != NULL);
1343 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1344 candidates = remote_desc->candidates(kMediaContentIndex0);
1345 ASSERT_EQ(2u, candidates->count());
1346 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1347 // Username and password have be updated with the TransportInfo of the
1348 // SessionDescription, won't be equal to the original one.
1349 candidate2.set_username(candidates->at(0)->candidate().username());
1350 candidate2.set_password(candidates->at(0)->candidate().password());
1351 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1352 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1353 // No need to verify the username and password.
1354 candidate1.set_username(candidates->at(1)->candidate().username());
1355 candidate1.set_password(candidates->at(1)->candidate().password());
1356 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1357
1358 // Test that the candidate is ignored if we can add the same candidate again.
1359 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1360}
1361
1362// Test that local candidates are added to the local session description and
1363// that they are retained if the local session description is changed.
1364TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1365 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001366 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 mediastream_signaling_.SendAudioVideoStream1();
1368 CreateAndSetRemoteOfferAndLocalAnswer();
1369
1370 const SessionDescriptionInterface* local_desc = session_->local_description();
1371 const IceCandidateCollection* candidates =
1372 local_desc->candidates(kMediaContentIndex0);
1373 ASSERT_TRUE(candidates != NULL);
1374 EXPECT_EQ(0u, candidates->count());
1375
1376 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1377
1378 local_desc = session_->local_description();
1379 candidates = local_desc->candidates(kMediaContentIndex0);
1380 ASSERT_TRUE(candidates != NULL);
1381 EXPECT_LT(0u, candidates->count());
1382 candidates = local_desc->candidates(1);
1383 ASSERT_TRUE(candidates != NULL);
1384 EXPECT_LT(0u, candidates->count());
1385
1386 // Update the session descriptions.
1387 mediastream_signaling_.SendAudioVideoStream1();
1388 CreateAndSetRemoteOfferAndLocalAnswer();
1389
1390 local_desc = session_->local_description();
1391 candidates = local_desc->candidates(kMediaContentIndex0);
1392 ASSERT_TRUE(candidates != NULL);
1393 EXPECT_LT(0u, candidates->count());
1394 candidates = local_desc->candidates(1);
1395 ASSERT_TRUE(candidates != NULL);
1396 EXPECT_LT(0u, candidates->count());
1397}
1398
1399// Test that we can set a remote session description with remote candidates.
1400TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001401 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001402
1403 cricket::Candidate candidate1;
1404 candidate1.set_component(1);
1405 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1406 candidate1);
1407 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001408 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001409
1410 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1411 SetRemoteDescriptionWithoutError(offer);
1412
1413 const SessionDescriptionInterface* remote_desc =
1414 session_->remote_description();
1415 ASSERT_TRUE(remote_desc != NULL);
1416 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1417 const IceCandidateCollection* candidates =
1418 remote_desc->candidates(kMediaContentIndex0);
1419 ASSERT_EQ(1u, candidates->count());
1420 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1421
wu@webrtc.org91053e72013-08-10 07:18:04 +00001422 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423 SetLocalDescriptionWithoutError(answer);
1424}
1425
1426// Test that offers and answers contains ice candidates when Ice candidates have
1427// been gathered.
1428TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1429 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001430 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001431 mediastream_signaling_.SendAudioVideoStream1();
1432 // Ice is started but candidates are not provided until SetLocalDescription
1433 // is called.
1434 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1435 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1436 CreateAndSetRemoteOfferAndLocalAnswer();
1437 // Wait until at least one local candidate has been collected.
1438 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1439 kIceCandidatesTimeout);
1440 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1441 kIceCandidatesTimeout);
1442
1443 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001444 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1446 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1447 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1448 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1449
1450 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1451 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001452 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001453 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1454 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1455 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1456 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1457 SetLocalDescriptionWithoutError(answer);
1458}
1459
1460// Verifies TransportProxy and media channels are created with content names
1461// present in the SessionDescription.
1462TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001463 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001464 mediastream_signaling_.SendAudioVideoStream1();
1465 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001466 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001467
1468 // CreateOffer creates session description with the content names "audio" and
1469 // "video". Goal is to modify these content names and verify transport channel
1470 // proxy in the BaseSession, as proxies are created with the content names
1471 // present in SDP.
1472 std::string sdp;
1473 EXPECT_TRUE(offer->ToString(&sdp));
1474 const std::string kAudioMid = "a=mid:audio";
1475 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1476 const std::string kVideoMid = "a=mid:video";
1477 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1478
1479 // Replacing |audio| with |audio_content_name|.
1480 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1481 kAudioMidReplaceStr.c_str(),
1482 kAudioMidReplaceStr.length(),
1483 &sdp);
1484 // Replacing |video| with |video_content_name|.
1485 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1486 kVideoMidReplaceStr.c_str(),
1487 kVideoMidReplaceStr.length(),
1488 &sdp);
1489
1490 SessionDescriptionInterface* modified_offer =
1491 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1492
1493 SetRemoteDescriptionWithoutError(modified_offer);
1494
1495 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001496 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 SetLocalDescriptionWithoutError(answer);
1498
1499 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1500 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1501 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1502 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1503}
1504
1505// Test that an offer contains the correct media content descriptions based on
1506// the send streams when no constraints have been set.
1507TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001508 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001510 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511 ASSERT_TRUE(offer != NULL);
1512 const cricket::ContentInfo* content =
1513 cricket::GetFirstAudioContent(offer->description());
1514 EXPECT_TRUE(content != NULL);
1515 content = cricket::GetFirstVideoContent(offer->description());
1516 EXPECT_TRUE(content == NULL);
1517}
1518
1519// Test that an offer contains the correct media content descriptions based on
1520// the send streams when no constraints have been set.
1521TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001522 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 // Test Audio only offer.
1524 mediastream_signaling_.UseOptionsAudioOnly();
1525 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001526 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527 const cricket::ContentInfo* content =
1528 cricket::GetFirstAudioContent(offer->description());
1529 EXPECT_TRUE(content != NULL);
1530 content = cricket::GetFirstVideoContent(offer->description());
1531 EXPECT_TRUE(content == NULL);
1532
1533 // Test Audio / Video offer.
1534 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001535 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 content = cricket::GetFirstAudioContent(offer->description());
1537 EXPECT_TRUE(content != NULL);
1538 content = cricket::GetFirstVideoContent(offer->description());
1539 EXPECT_TRUE(content != NULL);
1540}
1541
1542// Test that an offer contains no media content descriptions if
1543// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1544TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001545 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 webrtc::FakeConstraints constraints_no_receive;
1547 constraints_no_receive.SetMandatoryReceiveAudio(false);
1548 constraints_no_receive.SetMandatoryReceiveVideo(false);
1549
1550 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001551 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 ASSERT_TRUE(offer != NULL);
1553 const cricket::ContentInfo* content =
1554 cricket::GetFirstAudioContent(offer->description());
1555 EXPECT_TRUE(content == NULL);
1556 content = cricket::GetFirstVideoContent(offer->description());
1557 EXPECT_TRUE(content == NULL);
1558}
1559
1560// Test that an offer contains only audio media content descriptions if
1561// kOfferToReceiveAudio constraints are set to true.
1562TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001563 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 webrtc::FakeConstraints constraints_audio_only;
1565 constraints_audio_only.SetMandatoryReceiveAudio(true);
1566 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001567 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001568
1569 const cricket::ContentInfo* content =
1570 cricket::GetFirstAudioContent(offer->description());
1571 EXPECT_TRUE(content != NULL);
1572 content = cricket::GetFirstVideoContent(offer->description());
1573 EXPECT_TRUE(content == NULL);
1574}
1575
1576// Test that an offer contains audio and video media content descriptions if
1577// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1578TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001579 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580 // Test Audio / Video offer.
1581 webrtc::FakeConstraints constraints_audio_video;
1582 constraints_audio_video.SetMandatoryReceiveAudio(true);
1583 constraints_audio_video.SetMandatoryReceiveVideo(true);
1584 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001585 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 const cricket::ContentInfo* content =
1587 cricket::GetFirstAudioContent(offer->description());
1588
1589 EXPECT_TRUE(content != NULL);
1590 content = cricket::GetFirstVideoContent(offer->description());
1591 EXPECT_TRUE(content != NULL);
1592
1593 // TODO(perkj): Should the direction be set to SEND_ONLY if
1594 // The constraints is set to not receive audio or video but a track is added?
1595}
1596
1597// Test that an answer can not be created if the last remote description is not
1598// an offer.
1599TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001600 Init(NULL);
1601 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602 SetLocalDescriptionWithoutError(offer);
1603 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1604 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001605 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606}
1607
1608// Test that an answer contains the correct media content descriptions when no
1609// constraints have been set.
1610TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001611 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001612 // Create a remote offer with audio and video content.
1613 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1614 SetRemoteDescriptionWithoutError(offer.release());
1615 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001616 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 const cricket::ContentInfo* content =
1618 cricket::GetFirstAudioContent(answer->description());
1619 ASSERT_TRUE(content != NULL);
1620 EXPECT_FALSE(content->rejected);
1621
1622 content = cricket::GetFirstVideoContent(answer->description());
1623 ASSERT_TRUE(content != NULL);
1624 EXPECT_FALSE(content->rejected);
1625}
1626
1627// Test that an answer contains the correct media content descriptions when no
1628// constraints have been set and the offer only contain audio.
1629TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001630 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631 // Create a remote offer with audio only.
1632 cricket::MediaSessionOptions options;
1633 options.has_audio = true;
1634 options.has_video = false;
1635 talk_base::scoped_ptr<JsepSessionDescription> offer(
1636 CreateRemoteOffer(options));
1637 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1638 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1639
1640 SetRemoteDescriptionWithoutError(offer.release());
1641 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001642 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001643 const cricket::ContentInfo* content =
1644 cricket::GetFirstAudioContent(answer->description());
1645 ASSERT_TRUE(content != NULL);
1646 EXPECT_FALSE(content->rejected);
1647
1648 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1649}
1650
1651// Test that an answer contains the correct media content descriptions when no
1652// constraints have been set.
1653TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001654 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001655 // Create a remote offer with audio and video content.
1656 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1657 SetRemoteDescriptionWithoutError(offer.release());
1658 // Test with a stream with tracks.
1659 mediastream_signaling_.SendAudioVideoStream1();
1660 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001661 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662 const cricket::ContentInfo* content =
1663 cricket::GetFirstAudioContent(answer->description());
1664 ASSERT_TRUE(content != NULL);
1665 EXPECT_FALSE(content->rejected);
1666
1667 content = cricket::GetFirstVideoContent(answer->description());
1668 ASSERT_TRUE(content != NULL);
1669 EXPECT_FALSE(content->rejected);
1670}
1671
1672// Test that an answer contains the correct media content descriptions when
1673// constraints have been set but no stream is sent.
1674TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001675 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001676 // Create a remote offer with audio and video content.
1677 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1678 SetRemoteDescriptionWithoutError(offer.release());
1679
1680 webrtc::FakeConstraints constraints_no_receive;
1681 constraints_no_receive.SetMandatoryReceiveAudio(false);
1682 constraints_no_receive.SetMandatoryReceiveVideo(false);
1683
1684 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001685 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001686 const cricket::ContentInfo* content =
1687 cricket::GetFirstAudioContent(answer->description());
1688 ASSERT_TRUE(content != NULL);
1689 EXPECT_TRUE(content->rejected);
1690
1691 content = cricket::GetFirstVideoContent(answer->description());
1692 ASSERT_TRUE(content != NULL);
1693 EXPECT_TRUE(content->rejected);
1694}
1695
1696// Test that an answer contains the correct media content descriptions when
1697// constraints have been set and streams are sent.
1698TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001699 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700 // Create a remote offer with audio and video content.
1701 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1702 SetRemoteDescriptionWithoutError(offer.release());
1703
1704 webrtc::FakeConstraints constraints_no_receive;
1705 constraints_no_receive.SetMandatoryReceiveAudio(false);
1706 constraints_no_receive.SetMandatoryReceiveVideo(false);
1707
1708 // Test with a stream with tracks.
1709 mediastream_signaling_.SendAudioVideoStream1();
1710 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001711 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712
1713 // TODO(perkj): Should the direction be set to SEND_ONLY?
1714 const cricket::ContentInfo* content =
1715 cricket::GetFirstAudioContent(answer->description());
1716 ASSERT_TRUE(content != NULL);
1717 EXPECT_FALSE(content->rejected);
1718
1719 // TODO(perkj): Should the direction be set to SEND_ONLY?
1720 content = cricket::GetFirstVideoContent(answer->description());
1721 ASSERT_TRUE(content != NULL);
1722 EXPECT_FALSE(content->rejected);
1723}
1724
1725TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1726 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001727 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728 webrtc::FakeConstraints constraints;
1729 constraints.SetOptionalVAD(false);
1730 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001731 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001732 const cricket::ContentInfo* content =
1733 cricket::GetFirstAudioContent(offer->description());
1734 EXPECT_TRUE(content != NULL);
1735 EXPECT_TRUE(VerifyNoCNCodecs(content));
1736}
1737
1738TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1739 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001740 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 // Create a remote offer with audio and video content.
1742 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1743 SetRemoteDescriptionWithoutError(offer.release());
1744
1745 webrtc::FakeConstraints constraints;
1746 constraints.SetOptionalVAD(false);
1747 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001748 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001749 const cricket::ContentInfo* content =
1750 cricket::GetFirstAudioContent(answer->description());
1751 ASSERT_TRUE(content != NULL);
1752 EXPECT_TRUE(VerifyNoCNCodecs(content));
1753}
1754
1755// This test verifies the call setup when remote answer with audio only and
1756// later updates with video.
1757TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001758 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1760 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1761
1762 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001763 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764
1765 cricket::MediaSessionOptions options;
1766 options.has_video = false;
1767 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1768
1769 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1770 // and answer;
1771 SetLocalDescriptionWithoutError(offer);
1772 SetRemoteDescriptionWithoutError(answer);
1773
1774 video_channel_ = media_engine_->GetVideoChannel(0);
1775 voice_channel_ = media_engine_->GetVoiceChannel(0);
1776
1777 ASSERT_TRUE(video_channel_ == NULL);
1778
1779 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1780 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1781 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1782
1783 // Let the remote end update the session descriptions, with Audio and Video.
1784 mediastream_signaling_.SendAudioVideoStream2();
1785 CreateAndSetRemoteOfferAndLocalAnswer();
1786
1787 video_channel_ = media_engine_->GetVideoChannel(0);
1788 voice_channel_ = media_engine_->GetVoiceChannel(0);
1789
1790 ASSERT_TRUE(video_channel_ != NULL);
1791 ASSERT_TRUE(voice_channel_ != NULL);
1792
1793 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1794 ASSERT_EQ(1u, video_channel_->send_streams().size());
1795 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1796 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1797 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1798 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1799 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1800 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1801
1802 // Change session back to audio only.
1803 mediastream_signaling_.UseOptionsAudioOnly();
1804 CreateAndSetRemoteOfferAndLocalAnswer();
1805
1806 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1807 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1808 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1809 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1810 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1811}
1812
1813// This test verifies the call setup when remote answer with video only and
1814// later updates with audio.
1815TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001816 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001817 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1818 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1819 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001820 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821
1822 cricket::MediaSessionOptions options;
1823 options.has_audio = false;
1824 options.has_video = true;
1825 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1826 offer, options, cricket::SEC_ENABLED);
1827
1828 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1829 // and answer.
1830 SetLocalDescriptionWithoutError(offer);
1831 SetRemoteDescriptionWithoutError(answer);
1832
1833 video_channel_ = media_engine_->GetVideoChannel(0);
1834 voice_channel_ = media_engine_->GetVoiceChannel(0);
1835
1836 ASSERT_TRUE(voice_channel_ == NULL);
1837 ASSERT_TRUE(video_channel_ != NULL);
1838
1839 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1840 ASSERT_EQ(1u, video_channel_->send_streams().size());
1841 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1842
1843 // Update the session descriptions, with Audio and Video.
1844 mediastream_signaling_.SendAudioVideoStream2();
1845 CreateAndSetRemoteOfferAndLocalAnswer();
1846
1847 voice_channel_ = media_engine_->GetVoiceChannel(0);
1848 ASSERT_TRUE(voice_channel_ != NULL);
1849
1850 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1851 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1852 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1853 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1854
1855 // Change session back to video only.
1856 mediastream_signaling_.UseOptionsVideoOnly();
1857 CreateAndSetRemoteOfferAndLocalAnswer();
1858
1859 video_channel_ = media_engine_->GetVideoChannel(0);
1860 voice_channel_ = media_engine_->GetVoiceChannel(0);
1861
1862 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1863 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1864 ASSERT_EQ(1u, video_channel_->send_streams().size());
1865 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1866}
1867
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001869 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870 mediastream_signaling_.SendAudioVideoStream1();
1871 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001872 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873 VerifyCryptoParams(offer->description());
1874 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001875 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876 VerifyCryptoParams(answer->description());
1877}
1878
1879TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001880 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881 session_->set_secure_policy(cricket::SEC_DISABLED);
1882 mediastream_signaling_.SendAudioVideoStream1();
1883 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001884 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 VerifyNoCryptoParams(offer->description(), false);
1886}
1887
1888TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001889 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 VerifyAnswerFromNonCryptoOffer();
1891}
1892
1893TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001894 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001895 VerifyAnswerFromCryptoOffer();
1896}
1897
1898TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
1899 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
1900 // local description is removed by the application, BUNDLE flag should be
1901 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001902 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1904 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1905 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001906 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907 cricket::SessionDescription* offer_copy =
1908 offer->description()->Copy();
1909 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1910 JsepSessionDescription* modified_offer =
1911 new JsepSessionDescription(JsepSessionDescription::kOffer);
1912 modified_offer->Initialize(offer_copy, "1", "1");
1913
1914 SetLocalDescriptionWithoutError(modified_offer);
1915 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1916}
1917
1918TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001919 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920 mediastream_signaling_.SendAudioVideoStream1();
1921 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1922 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1923 FakeConstraints constraints;
1924 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001925 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001926 SetLocalDescriptionWithoutError(offer);
1927 mediastream_signaling_.SendAudioVideoStream2();
1928 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1929 CreateRemoteAnswer(session_->local_description()));
1930 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1931 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1932 JsepSessionDescription* modified_answer =
1933 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1934 modified_answer->Initialize(answer_copy, "1", "1");
1935 SetRemoteDescriptionWithoutError(modified_answer);
1936 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1937 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1938
1939 video_channel_ = media_engine_->GetVideoChannel(0);
1940 voice_channel_ = media_engine_->GetVoiceChannel(0);
1941
1942 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1943 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1944
1945 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1946 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1947
1948 ASSERT_EQ(1u, video_channel_->send_streams().size());
1949 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1950 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1951 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1952}
1953
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001954// This test verifies that SetLocalDescription and SetRemoteDescription fails
1955// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1956TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001957 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001958 mediastream_signaling_.SendAudioVideoStream1();
1959 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1960 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1961 FakeConstraints constraints;
1962 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001963 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001964 std::string offer_str;
1965 offer->ToString(&offer_str);
1966 // Disable rtcp-mux
1967 const std::string rtcp_mux = "rtcp-mux";
1968 const std::string xrtcp_mux = "xrtcp-mux";
1969 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1970 xrtcp_mux.c_str(), xrtcp_mux.length(),
1971 &offer_str);
1972 JsepSessionDescription *local_offer =
1973 new JsepSessionDescription(JsepSessionDescription::kOffer);
1974 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
1975 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
1976 JsepSessionDescription *remote_offer =
1977 new JsepSessionDescription(JsepSessionDescription::kOffer);
1978 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
1979 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
1980 // Trying unmodified SDP.
1981 SetLocalDescriptionWithoutError(offer);
1982}
1983
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001984TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001985 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986 mediastream_signaling_.SendAudioVideoStream1();
1987 CreateAndSetRemoteOfferAndLocalAnswer();
1988 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
1989 ASSERT_TRUE(channel != NULL);
1990 ASSERT_EQ(1u, channel->recv_streams().size());
1991 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
1992 double left_vol, right_vol;
1993 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1994 EXPECT_EQ(1, left_vol);
1995 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001996 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
1997 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1999 EXPECT_EQ(0, left_vol);
2000 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002001 EXPECT_EQ(0, renderer->channel_id());
2002 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2004 EXPECT_EQ(1, left_vol);
2005 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002006 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002007}
2008
2009TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002010 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011 mediastream_signaling_.SendAudioVideoStream1();
2012 CreateAndSetRemoteOfferAndLocalAnswer();
2013 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2014 ASSERT_TRUE(channel != NULL);
2015 ASSERT_EQ(1u, channel->send_streams().size());
2016 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2017 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2018
2019 cricket::AudioOptions options;
2020 options.echo_cancellation.Set(true);
2021
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002022 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2023 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002024 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2025 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002026 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002027
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002028 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2030 bool value;
2031 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2032 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002033 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034}
2035
2036TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002037 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038 mediastream_signaling_.SendAudioVideoStream1();
2039 CreateAndSetRemoteOfferAndLocalAnswer();
2040 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2041 ASSERT_TRUE(channel != NULL);
2042 ASSERT_LT(0u, channel->renderers().size());
2043 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2044 ASSERT_EQ(1u, channel->recv_streams().size());
2045 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2046 cricket::FakeVideoRenderer renderer;
2047 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2048 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2049 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2050 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2051}
2052
2053TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002054 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002055 mediastream_signaling_.SendAudioVideoStream1();
2056 CreateAndSetRemoteOfferAndLocalAnswer();
2057 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2058 ASSERT_TRUE(channel != NULL);
2059 ASSERT_EQ(1u, channel->send_streams().size());
2060 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2061 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2062 cricket::VideoOptions* options = NULL;
2063 session_->SetVideoSend(send_ssrc, false, options);
2064 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2065 session_->SetVideoSend(send_ssrc, true, options);
2066 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2067}
2068
2069TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2070 TestCanInsertDtmf(false);
2071}
2072
2073TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2074 TestCanInsertDtmf(true);
2075}
2076
2077TEST_F(WebRtcSessionTest, InsertDtmf) {
2078 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002079 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080 mediastream_signaling_.SendAudioVideoStream1();
2081 CreateAndSetRemoteOfferAndLocalAnswer();
2082 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2083 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2084
2085 // Insert DTMF
2086 const int expected_flags = DF_SEND;
2087 const int expected_duration = 90;
2088 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2089 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2090 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2091
2092 // Verify
2093 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2094 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2095 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2096 expected_duration, expected_flags));
2097 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2098 expected_duration, expected_flags));
2099 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2100 expected_duration, expected_flags));
2101}
2102
2103// This test verifies the |initiator| flag when session initiates the call.
2104TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002105 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002106 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002107 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2109 SetLocalDescriptionWithoutError(offer);
2110 EXPECT_TRUE(session_->initiator());
2111 SetRemoteDescriptionWithoutError(answer);
2112 EXPECT_TRUE(session_->initiator());
2113}
2114
2115// This test verifies the |initiator| flag when session receives the call.
2116TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002117 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118 EXPECT_FALSE(session_->initiator());
2119 SessionDescriptionInterface* offer = CreateRemoteOffer();
2120 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002121 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002122
2123 EXPECT_FALSE(session_->initiator());
2124 SetLocalDescriptionWithoutError(answer);
2125 EXPECT_FALSE(session_->initiator());
2126}
2127
2128// This test verifies the ice protocol type at initiator of the call
2129// if |a=ice-options:google-ice| is present in answer.
2130TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002131 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002132 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002133 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002134 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002135 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 SetLocalDescriptionWithoutError(offer);
2137 std::string sdp;
2138 EXPECT_TRUE(answer->ToString(&sdp));
2139 // Adding ice-options to the session level.
2140 InjectAfter("t=0 0\r\n",
2141 "a=ice-options:google-ice\r\n",
2142 &sdp);
2143 SessionDescriptionInterface* answer_with_gice =
2144 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2145 SetRemoteDescriptionWithoutError(answer_with_gice);
2146 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2147 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2148}
2149
2150// This test verifies the ice protocol type at initiator of the call
2151// if ICE RFC5245 is supported in answer.
2152TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002153 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002154 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002155 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2157 SetLocalDescriptionWithoutError(offer);
2158
2159 SetRemoteDescriptionWithoutError(answer);
2160 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2161 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2162}
2163
2164// This test verifies the ice protocol type at receiver side of the call if
2165// receiver decides to use google-ice.
2166TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002167 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002169 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002170 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002171 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002172 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 std::string sdp;
2174 EXPECT_TRUE(answer->ToString(&sdp));
2175 // Adding ice-options to the session level.
2176 InjectAfter("t=0 0\r\n",
2177 "a=ice-options:google-ice\r\n",
2178 &sdp);
2179 SessionDescriptionInterface* answer_with_gice =
2180 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2181 SetLocalDescriptionWithoutError(answer_with_gice);
2182 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2183 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2184}
2185
2186// This test verifies the ice protocol type at receiver side of the call if
2187// receiver decides to use ice RFC 5245.
2188TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002189 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002190 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002191 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002192 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002193 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194 SetLocalDescriptionWithoutError(answer);
2195 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2196 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2197}
2198
2199// This test verifies the session state when ICE RFC5245 in offer and
2200// ICE google-ice in answer.
2201TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002202 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002203 mediastream_signaling_.SendAudioVideoStream1();
2204 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002205 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002206 std::string offer_str;
2207 offer->ToString(&offer_str);
2208 // Disable google-ice
2209 const std::string gice_option = "google-ice";
2210 const std::string xgoogle_xice = "xgoogle-xice";
2211 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2212 xgoogle_xice.c_str(), xgoogle_xice.length(),
2213 &offer_str);
2214 JsepSessionDescription *ice_only_offer =
2215 new JsepSessionDescription(JsepSessionDescription::kOffer);
2216 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2217 SetLocalDescriptionWithoutError(ice_only_offer);
2218 std::string original_offer_sdp;
2219 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002220 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002222 original_offer_sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002223 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002224 pranswer_with_gice);
2225 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002227 original_offer_sdp, NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002228 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002229 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230}
2231
2232// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2233TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002234 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002236 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 SetLocalDescriptionWithoutError(offer);
2238 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2239 CreateRemoteAnswer(session_->local_description()));
2240
2241 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2242 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002243 JsepSessionDescription* modified_answer =
2244 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245
2246 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2247 answer->session_id(),
2248 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002249 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250
2251 // Modifying content names.
2252 std::string sdp;
2253 EXPECT_TRUE(answer->ToString(&sdp));
2254 const std::string kAudioMid = "a=mid:audio";
2255 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2256
2257 // Replacing |audio| with |audio_content_name|.
2258 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2259 kAudioMidReplaceStr.c_str(),
2260 kAudioMidReplaceStr.length(),
2261 &sdp);
2262
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002263 SessionDescriptionInterface* modified_answer1 =
2264 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2265 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266
2267 SetRemoteDescriptionWithoutError(answer.release());
2268}
2269
2270// Verifying remote offer and local answer have matching m-lines as per
2271// RFC 3264.
2272TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002273 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002274 mediastream_signaling_.SendAudioVideoStream1();
2275 SessionDescriptionInterface* offer = CreateRemoteOffer();
2276 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002277 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002278
2279 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2280 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002281 JsepSessionDescription* modified_answer =
2282 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002283
2284 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2285 answer->session_id(),
2286 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002287 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288 SetLocalDescriptionWithoutError(answer);
2289}
2290
2291// This test verifies that WebRtcSession does not start candidate allocation
2292// before SetLocalDescription is called.
2293TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002294 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295 mediastream_signaling_.SendAudioVideoStream1();
2296 SessionDescriptionInterface* offer = CreateRemoteOffer();
2297 cricket::Candidate candidate;
2298 candidate.set_component(1);
2299 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2300 candidate);
2301 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2302 cricket::Candidate candidate1;
2303 candidate1.set_component(1);
2304 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2305 candidate1);
2306 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2307 SetRemoteDescriptionWithoutError(offer);
2308 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2309 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2310
2311 // Pump for 1 second and verify that no candidates are generated.
2312 talk_base::Thread::Current()->ProcessMessages(1000);
2313 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2314 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2315
wu@webrtc.org91053e72013-08-10 07:18:04 +00002316 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002317 SetLocalDescriptionWithoutError(answer);
2318 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2319 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2320 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2321}
2322
2323// This test verifies that crypto parameter is updated in local session
2324// description as per security policy set in MediaSessionDescriptionFactory.
2325TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002326 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002327 mediastream_signaling_.SendAudioVideoStream1();
2328 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002329 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002330
2331 // Making sure SetLocalDescription correctly sets crypto value in
2332 // SessionDescription object after de-serialization of sdp string. The value
2333 // will be set as per MediaSessionDescriptionFactory.
2334 std::string offer_str;
2335 offer->ToString(&offer_str);
2336 SessionDescriptionInterface* jsep_offer_str =
2337 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2338 SetLocalDescriptionWithoutError(jsep_offer_str);
2339 EXPECT_TRUE(session_->voice_channel()->secure_required());
2340 EXPECT_TRUE(session_->video_channel()->secure_required());
2341}
2342
2343// This test verifies the crypto parameter when security is disabled.
2344TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002345 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346 mediastream_signaling_.SendAudioVideoStream1();
2347 session_->set_secure_policy(cricket::SEC_DISABLED);
2348 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002349 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350
2351 // Making sure SetLocalDescription correctly sets crypto value in
2352 // SessionDescription object after de-serialization of sdp string. The value
2353 // will be set as per MediaSessionDescriptionFactory.
2354 std::string offer_str;
2355 offer->ToString(&offer_str);
2356 SessionDescriptionInterface *jsep_offer_str =
2357 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2358 SetLocalDescriptionWithoutError(jsep_offer_str);
2359 EXPECT_FALSE(session_->voice_channel()->secure_required());
2360 EXPECT_FALSE(session_->video_channel()->secure_required());
2361}
2362
2363// This test verifies that an answer contains new ufrag and password if an offer
2364// with new ufrag and password is received.
2365TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002366 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002367 cricket::MediaSessionOptions options;
2368 options.has_audio = true;
2369 options.has_video = true;
2370 talk_base::scoped_ptr<JsepSessionDescription> offer(
2371 CreateRemoteOffer(options));
2372 SetRemoteDescriptionWithoutError(offer.release());
2373
2374 mediastream_signaling_.SendAudioVideoStream1();
2375 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002376 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002377 SetLocalDescriptionWithoutError(answer.release());
2378
2379 // Receive an offer with new ufrag and password.
2380 options.transport_options.ice_restart = true;
2381 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002382 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002383 SetRemoteDescriptionWithoutError(updated_offer1.release());
2384
2385 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002386 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002387
2388 CompareIceUfragAndPassword(updated_answer1->description(),
2389 session_->local_description()->description(),
2390 false);
2391
2392 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002393}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002394
wu@webrtc.org91053e72013-08-10 07:18:04 +00002395// This test verifies that an answer contains old ufrag and password if an offer
2396// with old ufrag and password is received.
2397TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2398 Init(NULL);
2399 cricket::MediaSessionOptions options;
2400 options.has_audio = true;
2401 options.has_video = true;
2402 talk_base::scoped_ptr<JsepSessionDescription> offer(
2403 CreateRemoteOffer(options));
2404 SetRemoteDescriptionWithoutError(offer.release());
2405
2406 mediastream_signaling_.SendAudioVideoStream1();
2407 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2408 CreateAnswer(NULL));
2409 SetLocalDescriptionWithoutError(answer.release());
2410
2411 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002412 options.transport_options.ice_restart = false;
2413 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002414 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002415 SetRemoteDescriptionWithoutError(updated_offer2.release());
2416
2417 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002418 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002419
2420 CompareIceUfragAndPassword(updated_answer2->description(),
2421 session_->local_description()->description(),
2422 true);
2423
2424 SetLocalDescriptionWithoutError(updated_answer2.release());
2425}
2426
2427TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002428 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002429 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002430 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002431 const std::string session_id_orig = offer->session_id();
2432 const std::string session_version_orig = offer->session_version();
2433 SetLocalDescriptionWithoutError(offer);
2434
2435 video_channel_ = media_engine_->GetVideoChannel(0);
2436 video_channel_->set_fail_set_send_codecs(true);
2437
2438 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002439 SessionDescriptionInterface* answer =
2440 CreateRemoteAnswer(session_->local_description());
2441 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002442}
2443
2444// Runs the loopback call test with BUNDLE and STUN disabled.
2445TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2446 // Lets try with only UDP ports.
2447 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2448 cricket::PORTALLOCATOR_DISABLE_TCP |
2449 cricket::PORTALLOCATOR_DISABLE_STUN |
2450 cricket::PORTALLOCATOR_DISABLE_RELAY);
2451 TestLoopbackCall();
2452}
2453
2454// Regression-test for a crash which should have been an error.
2455TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002456 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002457 cricket::MediaSessionOptions options;
2458 options.has_audio = true;
2459 options.has_video = true;
2460
2461 session_->SetError(cricket::BaseSession::ERROR_CONTENT);
2462 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2463 SessionDescriptionInterface* answer =
2464 CreateRemoteAnswer(offer, options);
2465 SetRemoteDescriptionExpectError(kSessionError, offer);
2466 SetLocalDescriptionExpectError(kSessionError, answer);
2467 // Not crashing is our success.
2468}
2469
2470TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2471 constraints_.reset(new FakeConstraints());
2472 constraints_->AddOptional(
2473 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002474 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002475
2476 SetLocalDescriptionWithDataChannel();
2477 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2478}
2479
2480TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2481 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2482
2483 constraints_.reset(new FakeConstraints());
2484 constraints_->AddOptional(
2485 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2486 constraints_->AddOptional(
2487 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002488 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002489
2490 SetLocalDescriptionWithDataChannel();
2491 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2492}
2493
wu@webrtc.org967bfff2013-09-19 05:49:50 +00002494TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2495 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2496
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002497 constraints_.reset(new FakeConstraints());
2498 constraints_->AddOptional(
2499 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2500 InitWithDtls(false);
2501
2502 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2503 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002504 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2505}
2506
2507TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2508 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2509 SetFactoryDtlsSrtp();
2510 constraints_.reset(new FakeConstraints());
2511 constraints_->AddOptional(
2512 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2513 InitWithDtls(false);
2514
2515 // Create remote offer with SCTP.
2516 cricket::MediaSessionOptions options;
2517 options.data_channel_type = cricket::DCT_SCTP;
2518 JsepSessionDescription* offer =
2519 CreateRemoteOffer(options, cricket::SEC_ENABLED);
2520 SetRemoteDescriptionWithoutError(offer);
2521
2522 // Verifies the answer contains SCTP.
2523 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2524 EXPECT_TRUE(answer != NULL);
2525 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
2526 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002527}
2528
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002529TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2530 constraints_.reset(new FakeConstraints());
2531 constraints_->AddOptional(
2532 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002533 constraints_->AddOptional(
2534 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
2535 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002536
2537 SetLocalDescriptionWithDataChannel();
2538 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2539}
2540
2541TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2542 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2543
2544 constraints_.reset(new FakeConstraints());
2545 constraints_->AddOptional(
2546 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002547 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002548
2549 SetLocalDescriptionWithDataChannel();
2550 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2551}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002552
2553// Verifies that CreateOffer succeeds when CreateOffer is called before async
2554// identity generation is finished.
2555TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
2556 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002557 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002558
2559 EXPECT_TRUE(session_->waiting_for_identity());
2560 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2561 EXPECT_TRUE(offer != NULL);
2562}
2563
2564// Verifies that CreateAnswer succeeds when CreateOffer is called before async
2565// identity generation is finished.
2566TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
2567 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002568 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002569
2570 cricket::MediaSessionOptions options;
2571 scoped_ptr<JsepSessionDescription> offer(
2572 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
2573 ASSERT_TRUE(offer.get() != NULL);
2574 SetRemoteDescriptionWithoutError(offer.release());
2575
2576 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2577 EXPECT_TRUE(answer != NULL);
2578}
2579
2580// Verifies that CreateOffer succeeds when CreateOffer is called after async
2581// identity generation is finished.
2582TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
2583 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002584 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002585
2586 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2587 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2588 EXPECT_TRUE(offer != NULL);
2589}
2590
2591// Verifies that CreateOffer fails when CreateOffer is called after async
2592// identity generation fails.
2593TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
2594 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002595 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002596
2597 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2598 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2599 EXPECT_TRUE(offer == NULL);
2600}
2601
2602// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
2603// before async identity generation is finished.
2604TEST_F(WebRtcSessionTest,
2605 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
2606 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2607 VerifyMultipleAsyncCreateDescription(
2608 true, CreateSessionDescriptionRequest::kOffer);
2609}
2610
2611// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
2612// before async identity generation fails.
2613TEST_F(WebRtcSessionTest,
2614 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
2615 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2616 VerifyMultipleAsyncCreateDescription(
2617 false, CreateSessionDescriptionRequest::kOffer);
2618}
2619
2620// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
2621// before async identity generation is finished.
2622TEST_F(WebRtcSessionTest,
2623 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
2624 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2625 VerifyMultipleAsyncCreateDescription(
2626 true, CreateSessionDescriptionRequest::kAnswer);
2627}
2628
2629// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
2630// before async identity generation fails.
2631TEST_F(WebRtcSessionTest,
2632 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
2633 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2634 VerifyMultipleAsyncCreateDescription(
2635 false, CreateSessionDescriptionRequest::kAnswer);
2636}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00002637
2638// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
2639// offer has no SDES crypto but only DTLS fingerprint.
2640TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
2641 // Init without DTLS.
2642 Init(NULL);
2643 // Create a remote offer with secured transport disabled.
2644 cricket::MediaSessionOptions options;
2645 JsepSessionDescription* offer(CreateRemoteOffer(
2646 options, cricket::SEC_DISABLED));
2647 // Adds a DTLS fingerprint to the remote offer.
2648 cricket::SessionDescription* sdp = offer->description();
2649 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
2650 ASSERT_TRUE(audio != NULL);
2651 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
2652 audio->description.identity_fingerprint.reset(
2653 talk_base::SSLFingerprint::CreateFromRfc4572(
2654 talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
2655 SetRemoteDescriptionExpectError(kSdpWithoutSdesAndDtlsDisabled,
2656 offer);
2657}
2658
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002659// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
2660// currently fails because upon disconnection and reconnection OnIceComplete is
2661// called more than once without returning to IceGatheringGathering.