blob: 1531e0efc1a09c0a5160fc01a204e12f8f9b3d6f [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/app/webrtc/audiotrack.h"
29#include "talk/app/webrtc/jsepicecandidate.h"
30#include "talk/app/webrtc/jsepsessiondescription.h"
31#include "talk/app/webrtc/mediastreamsignaling.h"
32#include "talk/app/webrtc/streamcollection.h"
33#include "talk/app/webrtc/videotrack.h"
34#include "talk/app/webrtc/test/fakeconstraints.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000035#include "talk/app/webrtc/test/fakedtlsidentityservice.h"
36#include "talk/app/webrtc/test/fakemediastreamsignaling.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/app/webrtc/webrtcsession.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000038#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039#include "talk/base/fakenetwork.h"
40#include "talk/base/firewallsocketserver.h"
41#include "talk/base/gunit.h"
42#include "talk/base/logging.h"
43#include "talk/base/network.h"
44#include "talk/base/physicalsocketserver.h"
45#include "talk/base/sslstreamadapter.h"
46#include "talk/base/stringutils.h"
47#include "talk/base/thread.h"
48#include "talk/base/virtualsocketserver.h"
49#include "talk/media/base/fakemediaengine.h"
50#include "talk/media/base/fakevideorenderer.h"
51#include "talk/media/base/mediachannel.h"
52#include "talk/media/devices/fakedevicemanager.h"
53#include "talk/p2p/base/stunserver.h"
54#include "talk/p2p/base/teststunserver.h"
55#include "talk/p2p/client/basicportallocator.h"
56#include "talk/session/media/channelmanager.h"
57#include "talk/session/media/mediasession.h"
58
59#define MAYBE_SKIP_TEST(feature) \
60 if (!(feature())) { \
61 LOG(LS_INFO) << "Feature disabled... skipping"; \
62 return; \
63 }
64
65using cricket::BaseSession;
66using cricket::DF_PLAY;
67using cricket::DF_SEND;
68using cricket::FakeVoiceMediaChannel;
69using cricket::NS_GINGLE_P2P;
70using cricket::NS_JINGLE_ICE_UDP;
71using cricket::TransportInfo;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072using talk_base::SocketAddress;
73using talk_base::scoped_ptr;
74using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000075using webrtc::CreateSessionDescriptionObserver;
76using webrtc::CreateSessionDescriptionRequest;
77using webrtc::DTLSIdentityRequestObserver;
78using webrtc::DTLSIdentityServiceInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079using webrtc::FakeConstraints;
80using webrtc::IceCandidateCollection;
81using webrtc::JsepIceCandidate;
82using webrtc::JsepSessionDescription;
83using webrtc::PeerConnectionInterface;
84using webrtc::SessionDescriptionInterface;
85using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000086using webrtc::WebRtcSession;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::kMlineMismatch;
88using webrtc::kSdpWithoutCrypto;
89using webrtc::kSessionError;
90using webrtc::kSetLocalSdpFailed;
91using webrtc::kSetRemoteSdpFailed;
92using webrtc::kPushDownAnswerTDFailed;
93using webrtc::kPushDownPranswerTDFailed;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000094using webrtc::kBundleWithoutRtcpMux;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095
96static const SocketAddress kClientAddr1("11.11.11.11", 0);
97static const SocketAddress kClientAddr2("22.22.22.22", 0);
98static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
99
100static const char kSessionVersion[] = "1";
101
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102// Media index of candidates belonging to the first media content.
103static const int kMediaContentIndex0 = 0;
104static const char kMediaContentName0[] = "audio";
105
106// Media index of candidates belonging to the second media content.
107static const int kMediaContentIndex1 = 1;
108static const char kMediaContentName1[] = "video";
109
110static const int kIceCandidatesTimeout = 10000;
111
112static const cricket::AudioCodec
113 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
114static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
115static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
116
117// Add some extra |newlines| to the |message| after |line|.
118static void InjectAfter(const std::string& line,
119 const std::string& newlines,
120 std::string* message) {
121 const std::string tmp = line + newlines;
122 talk_base::replace_substrs(line.c_str(), line.length(),
123 tmp.c_str(), tmp.length(), message);
124}
125
126class MockIceObserver : public webrtc::IceObserver {
127 public:
128 MockIceObserver()
129 : oncandidatesready_(false),
130 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
131 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
132 }
133
134 virtual void OnIceConnectionChange(
135 PeerConnectionInterface::IceConnectionState new_state) {
136 ice_connection_state_ = new_state;
137 }
138 virtual void OnIceGatheringChange(
139 PeerConnectionInterface::IceGatheringState new_state) {
140 // We can never transition back to "new".
141 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
142 ice_gathering_state_ = new_state;
143
144 // oncandidatesready_ really means "ICE gathering is complete".
145 // This if statement ensures that this value remains correct when we
146 // transition from kIceGatheringComplete to kIceGatheringGathering.
147 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
148 oncandidatesready_ = false;
149 }
150 }
151
152 // Found a new candidate.
153 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
154 if (candidate->sdp_mline_index() == kMediaContentIndex0) {
155 mline_0_candidates_.push_back(candidate->candidate());
156 } else if (candidate->sdp_mline_index() == kMediaContentIndex1) {
157 mline_1_candidates_.push_back(candidate->candidate());
158 }
159 // The ICE gathering state should always be Gathering when a candidate is
160 // received (or possibly Completed in the case of the final candidate).
161 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
162 }
163
164 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
165 virtual void OnIceComplete() {
166 EXPECT_FALSE(oncandidatesready_);
167 oncandidatesready_ = true;
168
169 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
170 // be called approximately simultaneously. For ease of testing, this
171 // check additionally requires that they be called in the above order.
172 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
173 ice_gathering_state_);
174 }
175
176 bool oncandidatesready_;
177 std::vector<cricket::Candidate> mline_0_candidates_;
178 std::vector<cricket::Candidate> mline_1_candidates_;
179 PeerConnectionInterface::IceConnectionState ice_connection_state_;
180 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
181};
182
183class WebRtcSessionForTest : public webrtc::WebRtcSession {
184 public:
185 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
186 talk_base::Thread* signaling_thread,
187 talk_base::Thread* worker_thread,
188 cricket::PortAllocator* port_allocator,
189 webrtc::IceObserver* ice_observer,
190 webrtc::MediaStreamSignaling* mediastream_signaling)
191 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
192 mediastream_signaling) {
193 RegisterIceObserver(ice_observer);
194 }
195 virtual ~WebRtcSessionForTest() {}
196
197 using cricket::BaseSession::GetTransportProxy;
198 using webrtc::WebRtcSession::SetAudioPlayout;
199 using webrtc::WebRtcSession::SetAudioSend;
200 using webrtc::WebRtcSession::SetCaptureDevice;
201 using webrtc::WebRtcSession::SetVideoPlayout;
202 using webrtc::WebRtcSession::SetVideoSend;
203};
204
wu@webrtc.org91053e72013-08-10 07:18:04 +0000205class WebRtcSessionCreateSDPObserverForTest
206 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000208 enum State {
209 kInit,
210 kFailed,
211 kSucceeded,
212 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000213 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000214
215 // CreateSessionDescriptionObserver implementation.
216 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000217 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000218 state_ = kSucceeded;
219 }
220 virtual void OnFailure(const std::string& error) {
221 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 }
223
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000224 SessionDescriptionInterface* description() { return description_.get(); }
225
226 SessionDescriptionInterface* ReleaseDescription() {
227 return description_.release();
228 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229
wu@webrtc.org91053e72013-08-10 07:18:04 +0000230 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231
wu@webrtc.org91053e72013-08-10 07:18:04 +0000232 protected:
233 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234
235 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000236 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000237 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238};
239
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000240class FakeAudioRenderer : public cricket::AudioRenderer {
241 public:
242 FakeAudioRenderer() : channel_id_(-1) {}
243
244 virtual void AddChannel(int channel_id) OVERRIDE {
245 ASSERT(channel_id_ == -1);
246 channel_id_ = channel_id;
247 }
248 virtual void RemoveChannel(int channel_id) OVERRIDE {
249 ASSERT(channel_id == channel_id_);
250 channel_id_ = -1;
251 }
252
253 int channel_id() const { return channel_id_; }
254 private:
255 int channel_id_;
256};
257
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258class WebRtcSessionTest : public testing::Test {
259 protected:
260 // TODO Investigate why ChannelManager crashes, if it's created
261 // after stun_server.
262 WebRtcSessionTest()
263 : media_engine_(new cricket::FakeMediaEngine()),
264 data_engine_(new cricket::FakeDataEngine()),
265 device_manager_(new cricket::FakeDeviceManager()),
266 channel_manager_(new cricket::ChannelManager(
267 media_engine_, data_engine_, device_manager_,
268 new cricket::CaptureManager(), talk_base::Thread::Current())),
269 tdesc_factory_(new cricket::TransportDescriptionFactory()),
270 desc_factory_(new cricket::MediaSessionDescriptionFactory(
271 channel_manager_.get(), tdesc_factory_.get())),
272 pss_(new talk_base::PhysicalSocketServer),
273 vss_(new talk_base::VirtualSocketServer(pss_.get())),
274 fss_(new talk_base::FirewallSocketServer(vss_.get())),
275 ss_scope_(fss_.get()),
276 stun_server_(talk_base::Thread::Current(), kStunAddr),
277 allocator_(&network_manager_, kStunAddr,
wu@webrtc.org967bfff2013-09-19 05:49:50 +0000278 SocketAddress(), SocketAddress(), SocketAddress()),
279 mediastream_signaling_(channel_manager_.get()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
281 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
282 cricket::PORTALLOCATOR_DISABLE_RELAY |
283 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
284 EXPECT_TRUE(channel_manager_->Init());
285 desc_factory_->set_add_legacy_streams(false);
286 }
287
288 void AddInterface(const SocketAddress& addr) {
289 network_manager_.AddInterface(addr);
290 }
291
wu@webrtc.org91053e72013-08-10 07:18:04 +0000292 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293 ASSERT_TRUE(session_.get() == NULL);
294 session_.reset(new WebRtcSessionForTest(
295 channel_manager_.get(), talk_base::Thread::Current(),
296 talk_base::Thread::Current(), &allocator_,
297 &observer_,
298 &mediastream_signaling_));
299
300 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
301 observer_.ice_connection_state_);
302 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
303 observer_.ice_gathering_state_);
304
wu@webrtc.org91053e72013-08-10 07:18:04 +0000305 EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000306 }
307
308 void InitWithDtmfCodec() {
309 // Add kTelephoneEventCodec for dtmf test.
310 std::vector<cricket::AudioCodec> codecs;
311 codecs.push_back(kTelephoneEventCodec);
312 media_engine_->SetAudioCodecs(codecs);
313 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000314 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000315 }
316
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000317 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000318 FakeIdentityService* identity_service = new FakeIdentityService();
319 identity_service->set_should_fail(identity_request_should_fail);
320 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 }
322
323 // Creates a local offer and applies it. Starts ice.
324 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
325 // to decide which streams to create.
326 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000327 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 SetLocalDescriptionWithoutError(offer);
329 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
330 observer_.ice_gathering_state_,
331 kIceCandidatesTimeout);
332 }
333
wu@webrtc.org91053e72013-08-10 07:18:04 +0000334 SessionDescriptionInterface* CreateOffer(
335 const webrtc::MediaConstraintsInterface* constraints) {
336 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
337 observer = new WebRtcSessionCreateSDPObserverForTest();
338 session_->CreateOffer(observer, constraints);
339 EXPECT_TRUE_WAIT(
340 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000341 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000342 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000343 }
344
345 SessionDescriptionInterface* CreateAnswer(
346 const webrtc::MediaConstraintsInterface* constraints) {
347 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
348 = new WebRtcSessionCreateSDPObserverForTest();
349 session_->CreateAnswer(observer, constraints);
350 EXPECT_TRUE_WAIT(
351 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000352 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000353 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000354 }
355
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 bool ChannelsExist() {
357 return (session_->voice_channel() != NULL &&
358 session_->video_channel() != NULL);
359 }
360
361 void CheckTransportChannels() {
362 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
363 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
364 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
365 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
366 }
367
368 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
369 ASSERT_TRUE(session_.get() != NULL);
370 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
371 ASSERT_TRUE(content != NULL);
372 const cricket::AudioContentDescription* audio_content =
373 static_cast<const cricket::AudioContentDescription*>(
374 content->description);
375 ASSERT_TRUE(audio_content != NULL);
376 ASSERT_EQ(1U, audio_content->cryptos().size());
377 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
378 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
379 audio_content->cryptos()[0].cipher_suite);
380 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
381 audio_content->protocol());
382
383 content = cricket::GetFirstVideoContent(sdp);
384 ASSERT_TRUE(content != NULL);
385 const cricket::VideoContentDescription* video_content =
386 static_cast<const cricket::VideoContentDescription*>(
387 content->description);
388 ASSERT_TRUE(video_content != NULL);
389 ASSERT_EQ(1U, video_content->cryptos().size());
390 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
391 video_content->cryptos()[0].cipher_suite);
392 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
393 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
394 video_content->protocol());
395 }
396
397 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
398 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
399 ASSERT_TRUE(content != NULL);
400 const cricket::AudioContentDescription* audio_content =
401 static_cast<const cricket::AudioContentDescription*>(
402 content->description);
403 ASSERT_TRUE(audio_content != NULL);
404 ASSERT_EQ(0U, audio_content->cryptos().size());
405
406 content = cricket::GetFirstVideoContent(sdp);
407 ASSERT_TRUE(content != NULL);
408 const cricket::VideoContentDescription* video_content =
409 static_cast<const cricket::VideoContentDescription*>(
410 content->description);
411 ASSERT_TRUE(video_content != NULL);
412 ASSERT_EQ(0U, video_content->cryptos().size());
413
414 if (dtls) {
415 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
416 audio_content->protocol());
417 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
418 video_content->protocol());
419 } else {
420 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
421 audio_content->protocol());
422 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
423 video_content->protocol());
424 }
425 }
426
427 // Set the internal fake description factories to do DTLS-SRTP.
428 void SetFactoryDtlsSrtp() {
429 desc_factory_->set_secure(cricket::SEC_ENABLED);
430 std::string identity_name = "WebRTC" +
431 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000432 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
433 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000434 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
435 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
436 }
437
438 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
439 bool expected) {
440 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
441 ASSERT_TRUE(audio != NULL);
442 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
443 if (expected) {
444 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
445 identity_fingerprint->algorithm);
446 }
447 const TransportInfo* video = sdp->GetTransportInfoByName("video");
448 ASSERT_TRUE(video != NULL);
449 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
450 if (expected) {
451 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
452 identity_fingerprint->algorithm);
453 }
454 }
455
456 void VerifyAnswerFromNonCryptoOffer() {
457 // Create a SDP without Crypto.
458 cricket::MediaSessionOptions options;
459 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000460 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000461 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000462 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000463 VerifyNoCryptoParams(offer->description(), false);
464 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
wu@webrtc.org91053e72013-08-10 07:18:04 +0000465 offer);
466 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 // Answer should be NULL as no crypto params in offer.
468 ASSERT_TRUE(answer == NULL);
469 }
470
471 void VerifyAnswerFromCryptoOffer() {
472 cricket::MediaSessionOptions options;
473 options.has_video = true;
474 options.bundle_enabled = true;
475 scoped_ptr<JsepSessionDescription> offer(
476 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
477 ASSERT_TRUE(offer.get() != NULL);
478 VerifyCryptoParams(offer->description());
479 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000480 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481 ASSERT_TRUE(answer.get() != NULL);
482 VerifyCryptoParams(answer->description());
483 }
484
485 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
486 const cricket::SessionDescription* desc2,
487 bool expect_equal) {
488 if (desc1->contents().size() != desc2->contents().size()) {
489 EXPECT_FALSE(expect_equal);
490 return;
491 }
492
493 const cricket::ContentInfos& contents = desc1->contents();
494 cricket::ContentInfos::const_iterator it = contents.begin();
495
496 for (; it != contents.end(); ++it) {
497 const cricket::TransportDescription* transport_desc1 =
498 desc1->GetTransportDescriptionByName(it->name);
499 const cricket::TransportDescription* transport_desc2 =
500 desc2->GetTransportDescriptionByName(it->name);
501 if (!transport_desc1 || !transport_desc2) {
502 EXPECT_FALSE(expect_equal);
503 return;
504 }
505 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
506 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
507 EXPECT_FALSE(expect_equal);
508 return;
509 }
510 }
511 EXPECT_TRUE(expect_equal);
512 }
513 // Creates a remote offer and and applies it as a remote description,
514 // creates a local answer and applies is as a local description.
515 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
516 // to decide which local and remote streams to create.
517 void CreateAndSetRemoteOfferAndLocalAnswer() {
518 SessionDescriptionInterface* offer = CreateRemoteOffer();
519 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000520 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 SetLocalDescriptionWithoutError(answer);
522 }
523 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
524 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
525 }
526 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
527 BaseSession::State expected_state) {
528 SetLocalDescriptionWithoutError(desc);
529 EXPECT_EQ(expected_state, session_->state());
530 }
531 void SetLocalDescriptionExpectError(const std::string& expected_error,
532 SessionDescriptionInterface* desc) {
533 std::string error;
534 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
535 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
536 EXPECT_NE(std::string::npos, error.find(expected_error));
537 }
538 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
539 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
540 }
541 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
542 BaseSession::State expected_state) {
543 SetRemoteDescriptionWithoutError(desc);
544 EXPECT_EQ(expected_state, session_->state());
545 }
546 void SetRemoteDescriptionExpectError(const std::string& expected_error,
547 SessionDescriptionInterface* desc) {
548 std::string error;
549 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
550 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
551 EXPECT_NE(std::string::npos, error.find(expected_error));
552 }
553
554 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
555 SessionDescriptionInterface** nocrypto_answer) {
556 // Create a SDP without Crypto.
557 cricket::MediaSessionOptions options;
558 options.has_video = true;
559 options.bundle_enabled = true;
560 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
561 ASSERT_TRUE(*offer != NULL);
562 VerifyCryptoParams((*offer)->description());
563
564 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
565 cricket::SEC_DISABLED);
566 EXPECT_TRUE(*nocrypto_answer != NULL);
567 }
568
569 JsepSessionDescription* CreateRemoteOfferWithVersion(
570 cricket::MediaSessionOptions options,
571 cricket::SecurePolicy secure_policy,
572 const std::string& session_version,
573 const SessionDescriptionInterface* current_desc) {
574 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
575 const cricket::SessionDescription* cricket_desc = NULL;
576 if (current_desc) {
577 cricket_desc = current_desc->description();
578 session_id = current_desc->session_id();
579 }
580
581 desc_factory_->set_secure(secure_policy);
582 JsepSessionDescription* offer(
583 new JsepSessionDescription(JsepSessionDescription::kOffer));
584 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
585 session_id, session_version)) {
586 delete offer;
587 offer = NULL;
588 }
589 return offer;
590 }
591 JsepSessionDescription* CreateRemoteOffer(
592 cricket::MediaSessionOptions options) {
593 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
594 kSessionVersion, NULL);
595 }
596 JsepSessionDescription* CreateRemoteOffer(
597 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
598 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
599 }
600 JsepSessionDescription* CreateRemoteOffer(
601 cricket::MediaSessionOptions options,
602 const SessionDescriptionInterface* current_desc) {
603 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
604 kSessionVersion, current_desc);
605 }
606
607 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
608 // before this function to decide which streams to create.
609 JsepSessionDescription* CreateRemoteOffer() {
610 cricket::MediaSessionOptions options;
611 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
612 return CreateRemoteOffer(options, session_->remote_description());
613 }
614
615 JsepSessionDescription* CreateRemoteAnswer(
616 const SessionDescriptionInterface* offer,
617 cricket::MediaSessionOptions options,
618 cricket::SecurePolicy policy) {
619 desc_factory_->set_secure(policy);
620 const std::string session_id =
621 talk_base::ToString(talk_base::CreateRandomId64());
622 JsepSessionDescription* answer(
623 new JsepSessionDescription(JsepSessionDescription::kAnswer));
624 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
625 options, NULL),
626 session_id, kSessionVersion)) {
627 delete answer;
628 answer = NULL;
629 }
630 return answer;
631 }
632
633 JsepSessionDescription* CreateRemoteAnswer(
634 const SessionDescriptionInterface* offer,
635 cricket::MediaSessionOptions options) {
636 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
637 }
638
639 // Creates an answer session description with streams based on
640 // |mediastream_signaling_|. Call
641 // mediastream_signaling_.UseOptionsWithStreamX() before this function
642 // to decide which streams to create.
643 JsepSessionDescription* CreateRemoteAnswer(
644 const SessionDescriptionInterface* offer) {
645 cricket::MediaSessionOptions options;
646 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
647 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
648 }
649
650 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
651 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000652 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000653 mediastream_signaling_.SendAudioVideoStream1();
654 FakeConstraints constraints;
655 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000656 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000657 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
658 // and answer.
659 SetLocalDescriptionWithoutError(offer);
660
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000661 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
662 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 std::string sdp;
664 EXPECT_TRUE(answer->ToString(&sdp));
665
666 size_t expected_candidate_num = 2;
667 if (!rtcp_mux) {
668 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
669 // for rtp and rtcp.
670 expected_candidate_num = 4;
671 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 const std::string kRtcpMux = "a=rtcp-mux";
673 const std::string kXRtcpMux = "a=xrtcp-mux";
674 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
675 kXRtcpMux.c_str(), kXRtcpMux.length(),
676 &sdp);
677 }
678
679 SessionDescriptionInterface* new_answer = CreateSessionDescription(
680 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681
682 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000683 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
685 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
686 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
687 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
688 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
689 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
690 if (bundle) {
691 EXPECT_TRUE(c0.IsEquivalent(c1));
692 } else {
693 EXPECT_FALSE(c0.IsEquivalent(c1));
694 }
695 }
696 }
697 // Tests that we can only send DTMF when the dtmf codec is supported.
698 void TestCanInsertDtmf(bool can) {
699 if (can) {
700 InitWithDtmfCodec();
701 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000702 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000703 }
704 mediastream_signaling_.SendAudioVideoStream1();
705 CreateAndSetRemoteOfferAndLocalAnswer();
706 EXPECT_FALSE(session_->CanInsertDtmf(""));
707 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
708 }
709
710 // The method sets up a call from the session to itself, in a loopback
711 // arrangement. It also uses a firewall rule to create a temporary
712 // disconnection. This code is placed as a method so that it can be invoked
713 // by multiple tests with different allocators (e.g. with and without BUNDLE).
714 // While running the call, this method also checks if the session goes through
715 // the correct sequence of ICE states when a connection is established,
716 // broken, and re-established.
717 // The Connection state should go:
718 // New -> Checking -> Connected -> Disconnected -> Connected.
719 // The Gathering state should go: New -> Gathering -> Completed.
720 void TestLoopbackCall() {
721 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000722 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000724 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725
726 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
727 observer_.ice_gathering_state_);
728 SetLocalDescriptionWithoutError(offer);
729 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
730 observer_.ice_connection_state_);
731 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
732 observer_.ice_gathering_state_,
733 kIceCandidatesTimeout);
734 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
735 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
736 observer_.ice_gathering_state_,
737 kIceCandidatesTimeout);
738
739 std::string sdp;
740 offer->ToString(&sdp);
741 SessionDescriptionInterface* desc =
742 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
743 ASSERT_TRUE(desc != NULL);
744 SetRemoteDescriptionWithoutError(desc);
745
746 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
747 observer_.ice_connection_state_,
748 kIceCandidatesTimeout);
749 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
750 observer_.ice_connection_state_,
751 kIceCandidatesTimeout);
752 // TODO(bemasc): EXPECT(Completed) once the details are standardized.
753
754 // Adding firewall rule to block ping requests, which should cause
755 // transport channel failure.
756 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
757 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
758 observer_.ice_connection_state_,
759 kIceCandidatesTimeout);
760
761 // Clearing the rules, session should move back to completed state.
762 fss_->ClearRules();
763 // Session is automatically calling OnSignalingReady after creation of
764 // new portallocator session which will allocate new set of candidates.
765
766 // TODO(bemasc): Change this to Completed once the details are standardized.
767 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
768 observer_.ice_connection_state_,
769 kIceCandidatesTimeout);
770 }
771
772 void VerifyTransportType(const std::string& content_name,
773 cricket::TransportProtocol protocol) {
774 const cricket::Transport* transport = session_->GetTransport(content_name);
775 ASSERT_TRUE(transport != NULL);
776 EXPECT_EQ(protocol, transport->protocol());
777 }
778
779 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
780 void AddCNCodecs() {
781 // Add kTelephoneEventCodec for dtmf test.
782 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
783 codecs.push_back(kCNCodec1);
784 codecs.push_back(kCNCodec2);
785 media_engine_->SetAudioCodecs(codecs);
786 desc_factory_->set_audio_codecs(codecs);
787 }
788
789 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
790 const cricket::ContentDescription* description = content->description;
791 ASSERT(description != NULL);
792 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000793 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000794 ASSERT(audio_content_desc != NULL);
795 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
796 if (audio_content_desc->codecs()[i].name == "CN")
797 return false;
798 }
799 return true;
800 }
801
802 void SetLocalDescriptionWithDataChannel() {
803 webrtc::DataChannelInit dci;
804 dci.reliable = false;
805 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000806 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 SetLocalDescriptionWithoutError(offer);
808 }
809
wu@webrtc.org91053e72013-08-10 07:18:04 +0000810 void VerifyMultipleAsyncCreateDescription(
811 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000812 InitWithDtls(!success);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000813
814 if (type == CreateSessionDescriptionRequest::kAnswer) {
815 cricket::MediaSessionOptions options;
816 scoped_ptr<JsepSessionDescription> offer(
817 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
818 ASSERT_TRUE(offer.get() != NULL);
819 SetRemoteDescriptionWithoutError(offer.release());
820 }
821
822 const int kNumber = 3;
823 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
824 observers[kNumber];
825 for (int i = 0; i < kNumber; ++i) {
826 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
827 if (type == CreateSessionDescriptionRequest::kOffer) {
828 session_->CreateOffer(observers[i], NULL);
829 } else {
830 session_->CreateAnswer(observers[i], NULL);
831 }
832 }
833
834 WebRtcSessionCreateSDPObserverForTest::State expected_state =
835 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
836 WebRtcSessionCreateSDPObserverForTest::kFailed;
837
838 for (int i = 0; i < kNumber; ++i) {
839 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
840 if (success) {
841 EXPECT_TRUE(observers[i]->description() != NULL);
842 } else {
843 EXPECT_TRUE(observers[i]->description() == NULL);
844 }
845 }
846 }
847
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848 cricket::FakeMediaEngine* media_engine_;
849 cricket::FakeDataEngine* data_engine_;
850 cricket::FakeDeviceManager* device_manager_;
851 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
852 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000853 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000854 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
855 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
856 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
857 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
858 talk_base::SocketServerScope ss_scope_;
859 cricket::TestStunServer stun_server_;
860 talk_base::FakeNetworkManager network_manager_;
861 cricket::BasicPortAllocator allocator_;
862 talk_base::scoped_ptr<FakeConstraints> constraints_;
863 FakeMediaStreamSignaling mediastream_signaling_;
864 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
865 MockIceObserver observer_;
866 cricket::FakeVideoMediaChannel* video_channel_;
867 cricket::FakeVoiceMediaChannel* voice_channel_;
868};
869
870TEST_F(WebRtcSessionTest, TestInitialize) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000871 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872}
873
874TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
875 InitWithDtls();
876}
877
wu@webrtc.org91053e72013-08-10 07:18:04 +0000878// Verifies that WebRtcSession uses SEC_REQUIRED by default.
879TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
880 Init(NULL);
881 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
882}
883
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000884TEST_F(WebRtcSessionTest, TestSessionCandidates) {
885 TestSessionCandidatesWithBundleRtcpMux(false, false);
886}
887
888// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
889// with rtcp-mux and/or bundle.
890TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
891 TestSessionCandidatesWithBundleRtcpMux(false, true);
892}
893
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
895 TestSessionCandidatesWithBundleRtcpMux(true, true);
896}
897
898TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
899 AddInterface(kClientAddr1);
900 AddInterface(kClientAddr2);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000901 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000902 mediastream_signaling_.SendAudioVideoStream1();
903 InitiateCall();
904 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
905 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
906 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
907}
908
909TEST_F(WebRtcSessionTest, TestStunError) {
910 AddInterface(kClientAddr1);
911 AddInterface(kClientAddr2);
912 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000913 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000914 mediastream_signaling_.SendAudioVideoStream1();
915 InitiateCall();
916 // Since kClientAddr1 is blocked, not expecting stun candidates for it.
917 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
918 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
919 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
920}
921
922// Test creating offers and receive answers and make sure the
923// media engine creates the expected send and receive streams.
924TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000925 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000927 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000928 const std::string session_id_orig = offer->session_id();
929 const std::string session_version_orig = offer->session_version();
930 SetLocalDescriptionWithoutError(offer);
931
932 mediastream_signaling_.SendAudioVideoStream2();
933 SessionDescriptionInterface* answer =
934 CreateRemoteAnswer(session_->local_description());
935 SetRemoteDescriptionWithoutError(answer);
936
937 video_channel_ = media_engine_->GetVideoChannel(0);
938 voice_channel_ = media_engine_->GetVoiceChannel(0);
939
940 ASSERT_EQ(1u, video_channel_->recv_streams().size());
941 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
942
943 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
944 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
945
946 ASSERT_EQ(1u, video_channel_->send_streams().size());
947 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
948 ASSERT_EQ(1u, voice_channel_->send_streams().size());
949 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
950
951 // Create new offer without send streams.
952 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000953 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000954
955 // Verify the session id is the same and the session version is
956 // increased.
957 EXPECT_EQ(session_id_orig, offer->session_id());
958 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
959 talk_base::FromString<uint64>(offer->session_version()));
960
961 SetLocalDescriptionWithoutError(offer);
962
963 mediastream_signaling_.SendAudioVideoStream2();
964 answer = CreateRemoteAnswer(session_->local_description());
965 SetRemoteDescriptionWithoutError(answer);
966
967 EXPECT_EQ(0u, video_channel_->send_streams().size());
968 EXPECT_EQ(0u, voice_channel_->send_streams().size());
969
970 // Make sure the receive streams have not changed.
971 ASSERT_EQ(1u, video_channel_->recv_streams().size());
972 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
973 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
974 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
975}
976
977// Test receiving offers and creating answers and make sure the
978// media engine creates the expected send and receive streams.
979TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000980 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000981 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000982 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000983 SetRemoteDescriptionWithoutError(offer);
984
985 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000986 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000987 SetLocalDescriptionWithoutError(answer);
988
989 const std::string session_id_orig = answer->session_id();
990 const std::string session_version_orig = answer->session_version();
991
992 video_channel_ = media_engine_->GetVideoChannel(0);
993 voice_channel_ = media_engine_->GetVoiceChannel(0);
994
995 ASSERT_EQ(1u, video_channel_->recv_streams().size());
996 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
997
998 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
999 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1000
1001 ASSERT_EQ(1u, video_channel_->send_streams().size());
1002 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1003 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1004 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1005
1006 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001007 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001008 SetRemoteDescriptionWithoutError(offer);
1009
1010 // Answer by turning off all send streams.
1011 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001012 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013
1014 // Verify the session id is the same and the session version is
1015 // increased.
1016 EXPECT_EQ(session_id_orig, answer->session_id());
1017 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1018 talk_base::FromString<uint64>(answer->session_version()));
1019 SetLocalDescriptionWithoutError(answer);
1020
1021 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1022 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1023 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1024 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1025 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1026 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1027
1028 // Make sure we have no send streams.
1029 EXPECT_EQ(0u, video_channel_->send_streams().size());
1030 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1031}
1032
1033// Test we will return fail when apply an offer that doesn't have
1034// crypto enabled.
1035TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001036 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 cricket::MediaSessionOptions options;
1038 options.has_video = true;
1039 JsepSessionDescription* offer = CreateRemoteOffer(
1040 options, cricket::SEC_DISABLED);
1041 ASSERT_TRUE(offer != NULL);
1042 VerifyNoCryptoParams(offer->description(), false);
1043 // SetRemoteDescription and SetLocalDescription will take the ownership of
1044 // the offer.
1045 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
1046 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1047 ASSERT_TRUE(offer != NULL);
1048 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
1049}
1050
1051// Test we will return fail when apply an answer that doesn't have
1052// crypto enabled.
1053TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001054 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055 SessionDescriptionInterface* offer = NULL;
1056 SessionDescriptionInterface* answer = NULL;
1057 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1058 // SetRemoteDescription and SetLocalDescription will take the ownership of
1059 // the offer.
1060 SetRemoteDescriptionWithoutError(offer);
1061 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
1062}
1063
1064// Test we will return fail when apply an answer that doesn't have
1065// crypto enabled.
1066TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001067 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001068 SessionDescriptionInterface* offer = NULL;
1069 SessionDescriptionInterface* answer = NULL;
1070 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1071 // SetRemoteDescription and SetLocalDescription will take the ownership of
1072 // the offer.
1073 SetLocalDescriptionWithoutError(offer);
1074 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
1075}
1076
1077// Test that we can create and set an offer with a DTLS fingerprint.
1078TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1079 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1080 InitWithDtls();
1081 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001082 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001083 ASSERT_TRUE(offer != NULL);
1084 VerifyFingerprintStatus(offer->description(), true);
1085 // SetLocalDescription will take the ownership of the offer.
1086 SetLocalDescriptionWithoutError(offer);
1087}
1088
1089// Test that we can process an offer with a DTLS fingerprint
1090// and that we return an answer with a fingerprint.
1091TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1092 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1093 InitWithDtls();
1094 SetFactoryDtlsSrtp();
1095 cricket::MediaSessionOptions options;
1096 options.has_video = true;
1097 JsepSessionDescription* offer = CreateRemoteOffer(options);
1098 ASSERT_TRUE(offer != NULL);
1099 VerifyFingerprintStatus(offer->description(), true);
1100
1101 // SetRemoteDescription will take the ownership of the offer.
1102 SetRemoteDescriptionWithoutError(offer);
1103
1104 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001105 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001106 ASSERT_TRUE(answer != NULL);
1107 VerifyFingerprintStatus(answer->description(), true);
1108 // Check that we don't have an a=crypto line in the answer.
1109 VerifyNoCryptoParams(answer->description(), true);
1110
1111 // Now set the local description, which should work, even without a=crypto.
1112 SetLocalDescriptionWithoutError(answer);
1113}
1114
1115// Test that even if we support DTLS, if the other side didn't offer a
1116// fingerprint, we don't either.
1117TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1118 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1119 InitWithDtls();
1120 cricket::MediaSessionOptions options;
1121 options.has_video = true;
1122 JsepSessionDescription* offer = CreateRemoteOffer(
1123 options, cricket::SEC_REQUIRED);
1124 ASSERT_TRUE(offer != NULL);
1125 VerifyFingerprintStatus(offer->description(), false);
1126
1127 // SetRemoteDescription will take the ownership of
1128 // the offer.
1129 SetRemoteDescriptionWithoutError(offer);
1130
1131 // Verify that we don't get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001132 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001133 ASSERT_TRUE(answer != NULL);
1134 VerifyFingerprintStatus(answer->description(), false);
1135
1136 // Now set the local description.
1137 SetLocalDescriptionWithoutError(answer);
1138}
1139
1140TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001141 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001142 mediastream_signaling_.SendNothing();
1143 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001144 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001145 SetLocalDescriptionWithoutError(offer);
1146
1147 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001148 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 SetLocalDescriptionWithoutError(offer2);
1150}
1151
1152TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001153 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 mediastream_signaling_.SendNothing();
1155 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001156 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 SetRemoteDescriptionWithoutError(offer);
1158
wu@webrtc.org91053e72013-08-10 07:18:04 +00001159 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 SetRemoteDescriptionWithoutError(offer2);
1161}
1162
1163TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001164 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001165 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001166 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001168 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001169 SetRemoteDescriptionExpectError(
1170 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
1171 offer);
1172}
1173
1174TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001175 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001177 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001179 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 SetLocalDescriptionExpectError(
1181 "Called with type in wrong state, type: "
1182 "offer state: STATE_RECEIVEDINITIATE",
1183 offer);
1184}
1185
1186TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001187 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 mediastream_signaling_.SendNothing();
1189 SessionDescriptionInterface* offer = CreateRemoteOffer();
1190 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1191
1192 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001193 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001194 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1195 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1196
1197 mediastream_signaling_.SendAudioVideoStream1();
1198 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001199 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001200 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1201
1202 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1203
1204 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001205 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001206 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1207}
1208
1209TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001210 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001211 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001212 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1214
1215 JsepSessionDescription* pranswer =
1216 CreateRemoteAnswer(session_->local_description());
1217 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1218
1219 SetRemoteDescriptionExpectState(pranswer,
1220 BaseSession::STATE_RECEIVEDPRACCEPT);
1221
1222 mediastream_signaling_.SendAudioVideoStream1();
1223 JsepSessionDescription* pranswer2 =
1224 CreateRemoteAnswer(session_->local_description());
1225 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1226
1227 SetRemoteDescriptionExpectState(pranswer2,
1228 BaseSession::STATE_RECEIVEDPRACCEPT);
1229
1230 mediastream_signaling_.SendAudioVideoStream2();
1231 SessionDescriptionInterface* answer =
1232 CreateRemoteAnswer(session_->local_description());
1233 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1234}
1235
1236TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001237 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 mediastream_signaling_.SendNothing();
1239 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001240 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001241 SessionDescriptionInterface* answer =
1242 CreateRemoteAnswer(offer.get());
1243 SetLocalDescriptionExpectError(
1244 "Called with type in wrong state, type: answer state: STATE_INIT",
1245 answer);
1246}
1247
1248TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001249 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250 mediastream_signaling_.SendNothing();
1251 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001252 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 SessionDescriptionInterface* answer =
1254 CreateRemoteAnswer(offer.get());
1255 SetRemoteDescriptionExpectError(
1256 "Called with type in wrong state, type: answer state: STATE_INIT",
1257 answer);
1258}
1259
1260TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001261 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 mediastream_signaling_.SendAudioVideoStream1();
1263
1264 cricket::Candidate candidate;
1265 candidate.set_component(1);
1266 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1267
1268 // Fail since we have not set a offer description.
1269 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1270
wu@webrtc.org91053e72013-08-10 07:18:04 +00001271 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 SetLocalDescriptionWithoutError(offer);
1273 // Candidate should be allowed to add before remote description.
1274 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1275 candidate.set_component(2);
1276 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1277 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1278
1279 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1280 session_->local_description());
1281 SetRemoteDescriptionWithoutError(answer);
1282
1283 // Verifying the candidates are copied properly from internal vector.
1284 const SessionDescriptionInterface* remote_desc =
1285 session_->remote_description();
1286 ASSERT_TRUE(remote_desc != NULL);
1287 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1288 const IceCandidateCollection* candidates =
1289 remote_desc->candidates(kMediaContentIndex0);
1290 ASSERT_EQ(2u, candidates->count());
1291 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1292 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1293 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1294 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1295
1296 candidate.set_component(2);
1297 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1298 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1299 ASSERT_EQ(3u, candidates->count());
1300
1301 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1302 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1303}
1304
1305// Test that a remote candidate is added to the remote session description and
1306// that it is retained if the remote session description is changed.
1307TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001308 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 cricket::Candidate candidate1;
1310 candidate1.set_component(1);
1311 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1312 candidate1);
1313 mediastream_signaling_.SendAudioVideoStream1();
1314 CreateAndSetRemoteOfferAndLocalAnswer();
1315
1316 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1317 const SessionDescriptionInterface* remote_desc =
1318 session_->remote_description();
1319 ASSERT_TRUE(remote_desc != NULL);
1320 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1321 const IceCandidateCollection* candidates =
1322 remote_desc->candidates(kMediaContentIndex0);
1323 ASSERT_EQ(1u, candidates->count());
1324 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1325
1326 // Update the RemoteSessionDescription with a new session description and
1327 // a candidate and check that the new remote session description contains both
1328 // candidates.
1329 SessionDescriptionInterface* offer = CreateRemoteOffer();
1330 cricket::Candidate candidate2;
1331 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1332 candidate2);
1333 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1334 SetRemoteDescriptionWithoutError(offer);
1335
1336 remote_desc = session_->remote_description();
1337 ASSERT_TRUE(remote_desc != NULL);
1338 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1339 candidates = remote_desc->candidates(kMediaContentIndex0);
1340 ASSERT_EQ(2u, candidates->count());
1341 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1342 // Username and password have be updated with the TransportInfo of the
1343 // SessionDescription, won't be equal to the original one.
1344 candidate2.set_username(candidates->at(0)->candidate().username());
1345 candidate2.set_password(candidates->at(0)->candidate().password());
1346 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1347 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1348 // No need to verify the username and password.
1349 candidate1.set_username(candidates->at(1)->candidate().username());
1350 candidate1.set_password(candidates->at(1)->candidate().password());
1351 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1352
1353 // Test that the candidate is ignored if we can add the same candidate again.
1354 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1355}
1356
1357// Test that local candidates are added to the local session description and
1358// that they are retained if the local session description is changed.
1359TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1360 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001361 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362 mediastream_signaling_.SendAudioVideoStream1();
1363 CreateAndSetRemoteOfferAndLocalAnswer();
1364
1365 const SessionDescriptionInterface* local_desc = session_->local_description();
1366 const IceCandidateCollection* candidates =
1367 local_desc->candidates(kMediaContentIndex0);
1368 ASSERT_TRUE(candidates != NULL);
1369 EXPECT_EQ(0u, candidates->count());
1370
1371 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1372
1373 local_desc = session_->local_description();
1374 candidates = local_desc->candidates(kMediaContentIndex0);
1375 ASSERT_TRUE(candidates != NULL);
1376 EXPECT_LT(0u, candidates->count());
1377 candidates = local_desc->candidates(1);
1378 ASSERT_TRUE(candidates != NULL);
1379 EXPECT_LT(0u, candidates->count());
1380
1381 // Update the session descriptions.
1382 mediastream_signaling_.SendAudioVideoStream1();
1383 CreateAndSetRemoteOfferAndLocalAnswer();
1384
1385 local_desc = session_->local_description();
1386 candidates = local_desc->candidates(kMediaContentIndex0);
1387 ASSERT_TRUE(candidates != NULL);
1388 EXPECT_LT(0u, candidates->count());
1389 candidates = local_desc->candidates(1);
1390 ASSERT_TRUE(candidates != NULL);
1391 EXPECT_LT(0u, candidates->count());
1392}
1393
1394// Test that we can set a remote session description with remote candidates.
1395TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001396 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397
1398 cricket::Candidate candidate1;
1399 candidate1.set_component(1);
1400 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1401 candidate1);
1402 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001403 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001404
1405 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1406 SetRemoteDescriptionWithoutError(offer);
1407
1408 const SessionDescriptionInterface* remote_desc =
1409 session_->remote_description();
1410 ASSERT_TRUE(remote_desc != NULL);
1411 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1412 const IceCandidateCollection* candidates =
1413 remote_desc->candidates(kMediaContentIndex0);
1414 ASSERT_EQ(1u, candidates->count());
1415 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1416
wu@webrtc.org91053e72013-08-10 07:18:04 +00001417 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001418 SetLocalDescriptionWithoutError(answer);
1419}
1420
1421// Test that offers and answers contains ice candidates when Ice candidates have
1422// been gathered.
1423TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1424 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001425 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001426 mediastream_signaling_.SendAudioVideoStream1();
1427 // Ice is started but candidates are not provided until SetLocalDescription
1428 // is called.
1429 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1430 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1431 CreateAndSetRemoteOfferAndLocalAnswer();
1432 // Wait until at least one local candidate has been collected.
1433 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1434 kIceCandidatesTimeout);
1435 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1436 kIceCandidatesTimeout);
1437
1438 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001439 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001440 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1441 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1442 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1443 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1444
1445 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1446 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001447 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001448 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1449 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1450 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1451 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1452 SetLocalDescriptionWithoutError(answer);
1453}
1454
1455// Verifies TransportProxy and media channels are created with content names
1456// present in the SessionDescription.
1457TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001458 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459 mediastream_signaling_.SendAudioVideoStream1();
1460 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001461 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001462
1463 // CreateOffer creates session description with the content names "audio" and
1464 // "video". Goal is to modify these content names and verify transport channel
1465 // proxy in the BaseSession, as proxies are created with the content names
1466 // present in SDP.
1467 std::string sdp;
1468 EXPECT_TRUE(offer->ToString(&sdp));
1469 const std::string kAudioMid = "a=mid:audio";
1470 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1471 const std::string kVideoMid = "a=mid:video";
1472 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1473
1474 // Replacing |audio| with |audio_content_name|.
1475 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1476 kAudioMidReplaceStr.c_str(),
1477 kAudioMidReplaceStr.length(),
1478 &sdp);
1479 // Replacing |video| with |video_content_name|.
1480 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1481 kVideoMidReplaceStr.c_str(),
1482 kVideoMidReplaceStr.length(),
1483 &sdp);
1484
1485 SessionDescriptionInterface* modified_offer =
1486 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1487
1488 SetRemoteDescriptionWithoutError(modified_offer);
1489
1490 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001491 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492 SetLocalDescriptionWithoutError(answer);
1493
1494 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1495 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1496 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1497 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1498}
1499
1500// Test that an offer contains the correct media content descriptions based on
1501// the send streams when no constraints have been set.
1502TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001503 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001505 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 ASSERT_TRUE(offer != NULL);
1507 const cricket::ContentInfo* content =
1508 cricket::GetFirstAudioContent(offer->description());
1509 EXPECT_TRUE(content != NULL);
1510 content = cricket::GetFirstVideoContent(offer->description());
1511 EXPECT_TRUE(content == NULL);
1512}
1513
1514// Test that an offer contains the correct media content descriptions based on
1515// the send streams when no constraints have been set.
1516TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001517 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 // Test Audio only offer.
1519 mediastream_signaling_.UseOptionsAudioOnly();
1520 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001521 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522 const cricket::ContentInfo* content =
1523 cricket::GetFirstAudioContent(offer->description());
1524 EXPECT_TRUE(content != NULL);
1525 content = cricket::GetFirstVideoContent(offer->description());
1526 EXPECT_TRUE(content == NULL);
1527
1528 // Test Audio / Video offer.
1529 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001530 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 content = cricket::GetFirstAudioContent(offer->description());
1532 EXPECT_TRUE(content != NULL);
1533 content = cricket::GetFirstVideoContent(offer->description());
1534 EXPECT_TRUE(content != NULL);
1535}
1536
1537// Test that an offer contains no media content descriptions if
1538// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1539TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001540 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001541 webrtc::FakeConstraints constraints_no_receive;
1542 constraints_no_receive.SetMandatoryReceiveAudio(false);
1543 constraints_no_receive.SetMandatoryReceiveVideo(false);
1544
1545 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001546 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 ASSERT_TRUE(offer != NULL);
1548 const cricket::ContentInfo* content =
1549 cricket::GetFirstAudioContent(offer->description());
1550 EXPECT_TRUE(content == NULL);
1551 content = cricket::GetFirstVideoContent(offer->description());
1552 EXPECT_TRUE(content == NULL);
1553}
1554
1555// Test that an offer contains only audio media content descriptions if
1556// kOfferToReceiveAudio constraints are set to true.
1557TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001558 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 webrtc::FakeConstraints constraints_audio_only;
1560 constraints_audio_only.SetMandatoryReceiveAudio(true);
1561 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001562 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563
1564 const cricket::ContentInfo* content =
1565 cricket::GetFirstAudioContent(offer->description());
1566 EXPECT_TRUE(content != NULL);
1567 content = cricket::GetFirstVideoContent(offer->description());
1568 EXPECT_TRUE(content == NULL);
1569}
1570
1571// Test that an offer contains audio and video media content descriptions if
1572// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1573TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001574 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001575 // Test Audio / Video offer.
1576 webrtc::FakeConstraints constraints_audio_video;
1577 constraints_audio_video.SetMandatoryReceiveAudio(true);
1578 constraints_audio_video.SetMandatoryReceiveVideo(true);
1579 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001580 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581 const cricket::ContentInfo* content =
1582 cricket::GetFirstAudioContent(offer->description());
1583
1584 EXPECT_TRUE(content != NULL);
1585 content = cricket::GetFirstVideoContent(offer->description());
1586 EXPECT_TRUE(content != NULL);
1587
1588 // TODO(perkj): Should the direction be set to SEND_ONLY if
1589 // The constraints is set to not receive audio or video but a track is added?
1590}
1591
1592// Test that an answer can not be created if the last remote description is not
1593// an offer.
1594TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001595 Init(NULL);
1596 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001597 SetLocalDescriptionWithoutError(offer);
1598 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1599 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001600 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001601}
1602
1603// Test that an answer contains the correct media content descriptions when no
1604// constraints have been set.
1605TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001606 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 // Create a remote offer with audio and video content.
1608 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1609 SetRemoteDescriptionWithoutError(offer.release());
1610 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001611 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001612 const cricket::ContentInfo* content =
1613 cricket::GetFirstAudioContent(answer->description());
1614 ASSERT_TRUE(content != NULL);
1615 EXPECT_FALSE(content->rejected);
1616
1617 content = cricket::GetFirstVideoContent(answer->description());
1618 ASSERT_TRUE(content != NULL);
1619 EXPECT_FALSE(content->rejected);
1620}
1621
1622// Test that an answer contains the correct media content descriptions when no
1623// constraints have been set and the offer only contain audio.
1624TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001625 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 // Create a remote offer with audio only.
1627 cricket::MediaSessionOptions options;
1628 options.has_audio = true;
1629 options.has_video = false;
1630 talk_base::scoped_ptr<JsepSessionDescription> offer(
1631 CreateRemoteOffer(options));
1632 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1633 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1634
1635 SetRemoteDescriptionWithoutError(offer.release());
1636 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001637 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638 const cricket::ContentInfo* content =
1639 cricket::GetFirstAudioContent(answer->description());
1640 ASSERT_TRUE(content != NULL);
1641 EXPECT_FALSE(content->rejected);
1642
1643 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1644}
1645
1646// Test that an answer contains the correct media content descriptions when no
1647// constraints have been set.
1648TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001649 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 // Create a remote offer with audio and video content.
1651 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1652 SetRemoteDescriptionWithoutError(offer.release());
1653 // Test with a stream with tracks.
1654 mediastream_signaling_.SendAudioVideoStream1();
1655 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001656 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657 const cricket::ContentInfo* content =
1658 cricket::GetFirstAudioContent(answer->description());
1659 ASSERT_TRUE(content != NULL);
1660 EXPECT_FALSE(content->rejected);
1661
1662 content = cricket::GetFirstVideoContent(answer->description());
1663 ASSERT_TRUE(content != NULL);
1664 EXPECT_FALSE(content->rejected);
1665}
1666
1667// Test that an answer contains the correct media content descriptions when
1668// constraints have been set but no stream is sent.
1669TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001670 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001671 // Create a remote offer with audio and video content.
1672 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1673 SetRemoteDescriptionWithoutError(offer.release());
1674
1675 webrtc::FakeConstraints constraints_no_receive;
1676 constraints_no_receive.SetMandatoryReceiveAudio(false);
1677 constraints_no_receive.SetMandatoryReceiveVideo(false);
1678
1679 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001680 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001681 const cricket::ContentInfo* content =
1682 cricket::GetFirstAudioContent(answer->description());
1683 ASSERT_TRUE(content != NULL);
1684 EXPECT_TRUE(content->rejected);
1685
1686 content = cricket::GetFirstVideoContent(answer->description());
1687 ASSERT_TRUE(content != NULL);
1688 EXPECT_TRUE(content->rejected);
1689}
1690
1691// Test that an answer contains the correct media content descriptions when
1692// constraints have been set and streams are sent.
1693TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001694 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 // Create a remote offer with audio and video content.
1696 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1697 SetRemoteDescriptionWithoutError(offer.release());
1698
1699 webrtc::FakeConstraints constraints_no_receive;
1700 constraints_no_receive.SetMandatoryReceiveAudio(false);
1701 constraints_no_receive.SetMandatoryReceiveVideo(false);
1702
1703 // Test with a stream with tracks.
1704 mediastream_signaling_.SendAudioVideoStream1();
1705 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001706 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707
1708 // TODO(perkj): Should the direction be set to SEND_ONLY?
1709 const cricket::ContentInfo* content =
1710 cricket::GetFirstAudioContent(answer->description());
1711 ASSERT_TRUE(content != NULL);
1712 EXPECT_FALSE(content->rejected);
1713
1714 // TODO(perkj): Should the direction be set to SEND_ONLY?
1715 content = cricket::GetFirstVideoContent(answer->description());
1716 ASSERT_TRUE(content != NULL);
1717 EXPECT_FALSE(content->rejected);
1718}
1719
1720TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1721 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001722 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001723 webrtc::FakeConstraints constraints;
1724 constraints.SetOptionalVAD(false);
1725 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001726 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001727 const cricket::ContentInfo* content =
1728 cricket::GetFirstAudioContent(offer->description());
1729 EXPECT_TRUE(content != NULL);
1730 EXPECT_TRUE(VerifyNoCNCodecs(content));
1731}
1732
1733TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1734 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001735 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001736 // Create a remote offer with audio and video content.
1737 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1738 SetRemoteDescriptionWithoutError(offer.release());
1739
1740 webrtc::FakeConstraints constraints;
1741 constraints.SetOptionalVAD(false);
1742 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001743 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001744 const cricket::ContentInfo* content =
1745 cricket::GetFirstAudioContent(answer->description());
1746 ASSERT_TRUE(content != NULL);
1747 EXPECT_TRUE(VerifyNoCNCodecs(content));
1748}
1749
1750// This test verifies the call setup when remote answer with audio only and
1751// later updates with video.
1752TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001753 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1755 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1756
1757 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001758 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759
1760 cricket::MediaSessionOptions options;
1761 options.has_video = false;
1762 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1763
1764 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1765 // and answer;
1766 SetLocalDescriptionWithoutError(offer);
1767 SetRemoteDescriptionWithoutError(answer);
1768
1769 video_channel_ = media_engine_->GetVideoChannel(0);
1770 voice_channel_ = media_engine_->GetVoiceChannel(0);
1771
1772 ASSERT_TRUE(video_channel_ == NULL);
1773
1774 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1775 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1776 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1777
1778 // Let the remote end update the session descriptions, with Audio and Video.
1779 mediastream_signaling_.SendAudioVideoStream2();
1780 CreateAndSetRemoteOfferAndLocalAnswer();
1781
1782 video_channel_ = media_engine_->GetVideoChannel(0);
1783 voice_channel_ = media_engine_->GetVoiceChannel(0);
1784
1785 ASSERT_TRUE(video_channel_ != NULL);
1786 ASSERT_TRUE(voice_channel_ != NULL);
1787
1788 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1789 ASSERT_EQ(1u, video_channel_->send_streams().size());
1790 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1791 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1792 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1793 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1794 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1795 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1796
1797 // Change session back to audio only.
1798 mediastream_signaling_.UseOptionsAudioOnly();
1799 CreateAndSetRemoteOfferAndLocalAnswer();
1800
1801 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1802 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1803 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1804 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1805 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1806}
1807
1808// This test verifies the call setup when remote answer with video only and
1809// later updates with audio.
1810TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001811 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001812 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1813 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1814 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001815 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816
1817 cricket::MediaSessionOptions options;
1818 options.has_audio = false;
1819 options.has_video = true;
1820 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1821 offer, options, cricket::SEC_ENABLED);
1822
1823 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1824 // and answer.
1825 SetLocalDescriptionWithoutError(offer);
1826 SetRemoteDescriptionWithoutError(answer);
1827
1828 video_channel_ = media_engine_->GetVideoChannel(0);
1829 voice_channel_ = media_engine_->GetVoiceChannel(0);
1830
1831 ASSERT_TRUE(voice_channel_ == NULL);
1832 ASSERT_TRUE(video_channel_ != NULL);
1833
1834 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1835 ASSERT_EQ(1u, video_channel_->send_streams().size());
1836 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1837
1838 // Update the session descriptions, with Audio and Video.
1839 mediastream_signaling_.SendAudioVideoStream2();
1840 CreateAndSetRemoteOfferAndLocalAnswer();
1841
1842 voice_channel_ = media_engine_->GetVoiceChannel(0);
1843 ASSERT_TRUE(voice_channel_ != NULL);
1844
1845 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1846 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1847 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1848 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1849
1850 // Change session back to video only.
1851 mediastream_signaling_.UseOptionsVideoOnly();
1852 CreateAndSetRemoteOfferAndLocalAnswer();
1853
1854 video_channel_ = media_engine_->GetVideoChannel(0);
1855 voice_channel_ = media_engine_->GetVoiceChannel(0);
1856
1857 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1858 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1859 ASSERT_EQ(1u, video_channel_->send_streams().size());
1860 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1861}
1862
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001864 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001865 mediastream_signaling_.SendAudioVideoStream1();
1866 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001867 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868 VerifyCryptoParams(offer->description());
1869 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001870 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001871 VerifyCryptoParams(answer->description());
1872}
1873
1874TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001875 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876 session_->set_secure_policy(cricket::SEC_DISABLED);
1877 mediastream_signaling_.SendAudioVideoStream1();
1878 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001879 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 VerifyNoCryptoParams(offer->description(), false);
1881}
1882
1883TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001884 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885 VerifyAnswerFromNonCryptoOffer();
1886}
1887
1888TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001889 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 VerifyAnswerFromCryptoOffer();
1891}
1892
1893TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
1894 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
1895 // local description is removed by the application, BUNDLE flag should be
1896 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001897 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001898 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1899 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1900 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001901 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001902 cricket::SessionDescription* offer_copy =
1903 offer->description()->Copy();
1904 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1905 JsepSessionDescription* modified_offer =
1906 new JsepSessionDescription(JsepSessionDescription::kOffer);
1907 modified_offer->Initialize(offer_copy, "1", "1");
1908
1909 SetLocalDescriptionWithoutError(modified_offer);
1910 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1911}
1912
1913TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001914 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915 mediastream_signaling_.SendAudioVideoStream1();
1916 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1917 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1918 FakeConstraints constraints;
1919 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001920 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921 SetLocalDescriptionWithoutError(offer);
1922 mediastream_signaling_.SendAudioVideoStream2();
1923 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1924 CreateRemoteAnswer(session_->local_description()));
1925 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1926 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1927 JsepSessionDescription* modified_answer =
1928 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1929 modified_answer->Initialize(answer_copy, "1", "1");
1930 SetRemoteDescriptionWithoutError(modified_answer);
1931 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1932 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1933
1934 video_channel_ = media_engine_->GetVideoChannel(0);
1935 voice_channel_ = media_engine_->GetVoiceChannel(0);
1936
1937 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1938 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1939
1940 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1941 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1942
1943 ASSERT_EQ(1u, video_channel_->send_streams().size());
1944 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1945 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1946 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1947}
1948
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001949// This test verifies that SetLocalDescription and SetRemoteDescription fails
1950// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1951TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001952 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001953 mediastream_signaling_.SendAudioVideoStream1();
1954 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1955 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1956 FakeConstraints constraints;
1957 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001958 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001959 std::string offer_str;
1960 offer->ToString(&offer_str);
1961 // Disable rtcp-mux
1962 const std::string rtcp_mux = "rtcp-mux";
1963 const std::string xrtcp_mux = "xrtcp-mux";
1964 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1965 xrtcp_mux.c_str(), xrtcp_mux.length(),
1966 &offer_str);
1967 JsepSessionDescription *local_offer =
1968 new JsepSessionDescription(JsepSessionDescription::kOffer);
1969 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
1970 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
1971 JsepSessionDescription *remote_offer =
1972 new JsepSessionDescription(JsepSessionDescription::kOffer);
1973 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
1974 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
1975 // Trying unmodified SDP.
1976 SetLocalDescriptionWithoutError(offer);
1977}
1978
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001979TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001980 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001981 mediastream_signaling_.SendAudioVideoStream1();
1982 CreateAndSetRemoteOfferAndLocalAnswer();
1983 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
1984 ASSERT_TRUE(channel != NULL);
1985 ASSERT_EQ(1u, channel->recv_streams().size());
1986 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
1987 double left_vol, right_vol;
1988 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1989 EXPECT_EQ(1, left_vol);
1990 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001991 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
1992 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001993 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1994 EXPECT_EQ(0, left_vol);
1995 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001996 EXPECT_EQ(0, renderer->channel_id());
1997 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1999 EXPECT_EQ(1, left_vol);
2000 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002001 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002002}
2003
2004TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002005 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002006 mediastream_signaling_.SendAudioVideoStream1();
2007 CreateAndSetRemoteOfferAndLocalAnswer();
2008 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2009 ASSERT_TRUE(channel != NULL);
2010 ASSERT_EQ(1u, channel->send_streams().size());
2011 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2012 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2013
2014 cricket::AudioOptions options;
2015 options.echo_cancellation.Set(true);
2016
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002017 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2018 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002019 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2020 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002021 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002023 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002024 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2025 bool value;
2026 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2027 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002028 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029}
2030
2031TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002032 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033 mediastream_signaling_.SendAudioVideoStream1();
2034 CreateAndSetRemoteOfferAndLocalAnswer();
2035 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2036 ASSERT_TRUE(channel != NULL);
2037 ASSERT_LT(0u, channel->renderers().size());
2038 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2039 ASSERT_EQ(1u, channel->recv_streams().size());
2040 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2041 cricket::FakeVideoRenderer renderer;
2042 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2043 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2044 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2045 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2046}
2047
2048TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002049 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050 mediastream_signaling_.SendAudioVideoStream1();
2051 CreateAndSetRemoteOfferAndLocalAnswer();
2052 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2053 ASSERT_TRUE(channel != NULL);
2054 ASSERT_EQ(1u, channel->send_streams().size());
2055 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2056 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2057 cricket::VideoOptions* options = NULL;
2058 session_->SetVideoSend(send_ssrc, false, options);
2059 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2060 session_->SetVideoSend(send_ssrc, true, options);
2061 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2062}
2063
2064TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2065 TestCanInsertDtmf(false);
2066}
2067
2068TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2069 TestCanInsertDtmf(true);
2070}
2071
2072TEST_F(WebRtcSessionTest, InsertDtmf) {
2073 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002074 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075 mediastream_signaling_.SendAudioVideoStream1();
2076 CreateAndSetRemoteOfferAndLocalAnswer();
2077 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2078 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2079
2080 // Insert DTMF
2081 const int expected_flags = DF_SEND;
2082 const int expected_duration = 90;
2083 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2084 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2085 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2086
2087 // Verify
2088 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2089 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2090 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2091 expected_duration, expected_flags));
2092 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2093 expected_duration, expected_flags));
2094 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2095 expected_duration, expected_flags));
2096}
2097
2098// This test verifies the |initiator| flag when session initiates the call.
2099TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002100 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002101 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002102 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002103 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2104 SetLocalDescriptionWithoutError(offer);
2105 EXPECT_TRUE(session_->initiator());
2106 SetRemoteDescriptionWithoutError(answer);
2107 EXPECT_TRUE(session_->initiator());
2108}
2109
2110// This test verifies the |initiator| flag when session receives the call.
2111TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002112 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002113 EXPECT_FALSE(session_->initiator());
2114 SessionDescriptionInterface* offer = CreateRemoteOffer();
2115 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002116 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002117
2118 EXPECT_FALSE(session_->initiator());
2119 SetLocalDescriptionWithoutError(answer);
2120 EXPECT_FALSE(session_->initiator());
2121}
2122
2123// This test verifies the ice protocol type at initiator of the call
2124// if |a=ice-options:google-ice| is present in answer.
2125TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002126 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002128 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002129 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002130 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002131 SetLocalDescriptionWithoutError(offer);
2132 std::string sdp;
2133 EXPECT_TRUE(answer->ToString(&sdp));
2134 // Adding ice-options to the session level.
2135 InjectAfter("t=0 0\r\n",
2136 "a=ice-options:google-ice\r\n",
2137 &sdp);
2138 SessionDescriptionInterface* answer_with_gice =
2139 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2140 SetRemoteDescriptionWithoutError(answer_with_gice);
2141 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2142 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2143}
2144
2145// This test verifies the ice protocol type at initiator of the call
2146// if ICE RFC5245 is supported in answer.
2147TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002148 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002149 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002150 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002151 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2152 SetLocalDescriptionWithoutError(offer);
2153
2154 SetRemoteDescriptionWithoutError(answer);
2155 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2156 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2157}
2158
2159// This test verifies the ice protocol type at receiver side of the call if
2160// receiver decides to use google-ice.
2161TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002162 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002164 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002165 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002166 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002167 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168 std::string sdp;
2169 EXPECT_TRUE(answer->ToString(&sdp));
2170 // Adding ice-options to the session level.
2171 InjectAfter("t=0 0\r\n",
2172 "a=ice-options:google-ice\r\n",
2173 &sdp);
2174 SessionDescriptionInterface* answer_with_gice =
2175 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2176 SetLocalDescriptionWithoutError(answer_with_gice);
2177 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2178 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2179}
2180
2181// This test verifies the ice protocol type at receiver side of the call if
2182// receiver decides to use ice RFC 5245.
2183TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002184 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002186 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002187 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002188 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002189 SetLocalDescriptionWithoutError(answer);
2190 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2191 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2192}
2193
2194// This test verifies the session state when ICE RFC5245 in offer and
2195// ICE google-ice in answer.
2196TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002197 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198 mediastream_signaling_.SendAudioVideoStream1();
2199 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002200 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002201 std::string offer_str;
2202 offer->ToString(&offer_str);
2203 // Disable google-ice
2204 const std::string gice_option = "google-ice";
2205 const std::string xgoogle_xice = "xgoogle-xice";
2206 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2207 xgoogle_xice.c_str(), xgoogle_xice.length(),
2208 &offer_str);
2209 JsepSessionDescription *ice_only_offer =
2210 new JsepSessionDescription(JsepSessionDescription::kOffer);
2211 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2212 SetLocalDescriptionWithoutError(ice_only_offer);
2213 std::string original_offer_sdp;
2214 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002215 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002216 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002217 original_offer_sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002219 pranswer_with_gice);
2220 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002222 original_offer_sdp, NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002223 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002224 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002225}
2226
2227// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2228TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002229 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002231 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002232 SetLocalDescriptionWithoutError(offer);
2233 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2234 CreateRemoteAnswer(session_->local_description()));
2235
2236 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2237 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002238 JsepSessionDescription* modified_answer =
2239 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002240
2241 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2242 answer->session_id(),
2243 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002244 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245
2246 // Modifying content names.
2247 std::string sdp;
2248 EXPECT_TRUE(answer->ToString(&sdp));
2249 const std::string kAudioMid = "a=mid:audio";
2250 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2251
2252 // Replacing |audio| with |audio_content_name|.
2253 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2254 kAudioMidReplaceStr.c_str(),
2255 kAudioMidReplaceStr.length(),
2256 &sdp);
2257
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002258 SessionDescriptionInterface* modified_answer1 =
2259 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2260 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002261
2262 SetRemoteDescriptionWithoutError(answer.release());
2263}
2264
2265// Verifying remote offer and local answer have matching m-lines as per
2266// RFC 3264.
2267TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002268 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002269 mediastream_signaling_.SendAudioVideoStream1();
2270 SessionDescriptionInterface* offer = CreateRemoteOffer();
2271 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002272 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002273
2274 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2275 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002276 JsepSessionDescription* modified_answer =
2277 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002278
2279 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2280 answer->session_id(),
2281 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002282 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002283 SetLocalDescriptionWithoutError(answer);
2284}
2285
2286// This test verifies that WebRtcSession does not start candidate allocation
2287// before SetLocalDescription is called.
2288TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002289 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002290 mediastream_signaling_.SendAudioVideoStream1();
2291 SessionDescriptionInterface* offer = CreateRemoteOffer();
2292 cricket::Candidate candidate;
2293 candidate.set_component(1);
2294 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2295 candidate);
2296 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2297 cricket::Candidate candidate1;
2298 candidate1.set_component(1);
2299 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2300 candidate1);
2301 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2302 SetRemoteDescriptionWithoutError(offer);
2303 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2304 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2305
2306 // Pump for 1 second and verify that no candidates are generated.
2307 talk_base::Thread::Current()->ProcessMessages(1000);
2308 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2309 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2310
wu@webrtc.org91053e72013-08-10 07:18:04 +00002311 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002312 SetLocalDescriptionWithoutError(answer);
2313 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2314 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2315 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2316}
2317
2318// This test verifies that crypto parameter is updated in local session
2319// description as per security policy set in MediaSessionDescriptionFactory.
2320TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002321 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002322 mediastream_signaling_.SendAudioVideoStream1();
2323 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002324 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002325
2326 // Making sure SetLocalDescription correctly sets crypto value in
2327 // SessionDescription object after de-serialization of sdp string. The value
2328 // will be set as per MediaSessionDescriptionFactory.
2329 std::string offer_str;
2330 offer->ToString(&offer_str);
2331 SessionDescriptionInterface* jsep_offer_str =
2332 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2333 SetLocalDescriptionWithoutError(jsep_offer_str);
2334 EXPECT_TRUE(session_->voice_channel()->secure_required());
2335 EXPECT_TRUE(session_->video_channel()->secure_required());
2336}
2337
2338// This test verifies the crypto parameter when security is disabled.
2339TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002340 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002341 mediastream_signaling_.SendAudioVideoStream1();
2342 session_->set_secure_policy(cricket::SEC_DISABLED);
2343 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002344 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002345
2346 // Making sure SetLocalDescription correctly sets crypto value in
2347 // SessionDescription object after de-serialization of sdp string. The value
2348 // will be set as per MediaSessionDescriptionFactory.
2349 std::string offer_str;
2350 offer->ToString(&offer_str);
2351 SessionDescriptionInterface *jsep_offer_str =
2352 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2353 SetLocalDescriptionWithoutError(jsep_offer_str);
2354 EXPECT_FALSE(session_->voice_channel()->secure_required());
2355 EXPECT_FALSE(session_->video_channel()->secure_required());
2356}
2357
2358// This test verifies that an answer contains new ufrag and password if an offer
2359// with new ufrag and password is received.
2360TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002361 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002362 cricket::MediaSessionOptions options;
2363 options.has_audio = true;
2364 options.has_video = true;
2365 talk_base::scoped_ptr<JsepSessionDescription> offer(
2366 CreateRemoteOffer(options));
2367 SetRemoteDescriptionWithoutError(offer.release());
2368
2369 mediastream_signaling_.SendAudioVideoStream1();
2370 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002371 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372 SetLocalDescriptionWithoutError(answer.release());
2373
2374 // Receive an offer with new ufrag and password.
2375 options.transport_options.ice_restart = true;
2376 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002377 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002378 SetRemoteDescriptionWithoutError(updated_offer1.release());
2379
2380 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002381 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002382
2383 CompareIceUfragAndPassword(updated_answer1->description(),
2384 session_->local_description()->description(),
2385 false);
2386
2387 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002388}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002389
wu@webrtc.org91053e72013-08-10 07:18:04 +00002390// This test verifies that an answer contains old ufrag and password if an offer
2391// with old ufrag and password is received.
2392TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2393 Init(NULL);
2394 cricket::MediaSessionOptions options;
2395 options.has_audio = true;
2396 options.has_video = true;
2397 talk_base::scoped_ptr<JsepSessionDescription> offer(
2398 CreateRemoteOffer(options));
2399 SetRemoteDescriptionWithoutError(offer.release());
2400
2401 mediastream_signaling_.SendAudioVideoStream1();
2402 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2403 CreateAnswer(NULL));
2404 SetLocalDescriptionWithoutError(answer.release());
2405
2406 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002407 options.transport_options.ice_restart = false;
2408 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002409 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002410 SetRemoteDescriptionWithoutError(updated_offer2.release());
2411
2412 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002413 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002414
2415 CompareIceUfragAndPassword(updated_answer2->description(),
2416 session_->local_description()->description(),
2417 true);
2418
2419 SetLocalDescriptionWithoutError(updated_answer2.release());
2420}
2421
2422TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002423 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002424 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002425 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002426 const std::string session_id_orig = offer->session_id();
2427 const std::string session_version_orig = offer->session_version();
2428 SetLocalDescriptionWithoutError(offer);
2429
2430 video_channel_ = media_engine_->GetVideoChannel(0);
2431 video_channel_->set_fail_set_send_codecs(true);
2432
2433 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002434 SessionDescriptionInterface* answer =
2435 CreateRemoteAnswer(session_->local_description());
2436 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002437}
2438
2439// Runs the loopback call test with BUNDLE and STUN disabled.
2440TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2441 // Lets try with only UDP ports.
2442 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2443 cricket::PORTALLOCATOR_DISABLE_TCP |
2444 cricket::PORTALLOCATOR_DISABLE_STUN |
2445 cricket::PORTALLOCATOR_DISABLE_RELAY);
2446 TestLoopbackCall();
2447}
2448
2449// Regression-test for a crash which should have been an error.
2450TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002451 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002452 cricket::MediaSessionOptions options;
2453 options.has_audio = true;
2454 options.has_video = true;
2455
2456 session_->SetError(cricket::BaseSession::ERROR_CONTENT);
2457 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2458 SessionDescriptionInterface* answer =
2459 CreateRemoteAnswer(offer, options);
2460 SetRemoteDescriptionExpectError(kSessionError, offer);
2461 SetLocalDescriptionExpectError(kSessionError, answer);
2462 // Not crashing is our success.
2463}
2464
2465TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2466 constraints_.reset(new FakeConstraints());
2467 constraints_->AddOptional(
2468 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002469 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002470
2471 SetLocalDescriptionWithDataChannel();
2472 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2473}
2474
2475TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2476 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2477
2478 constraints_.reset(new FakeConstraints());
2479 constraints_->AddOptional(
2480 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2481 constraints_->AddOptional(
2482 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002483 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002484
2485 SetLocalDescriptionWithDataChannel();
2486 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2487}
2488
wu@webrtc.org967bfff2013-09-19 05:49:50 +00002489TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2490 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2491
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002492 constraints_.reset(new FakeConstraints());
2493 constraints_->AddOptional(
2494 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2495 InitWithDtls(false);
2496
2497 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2498 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002499 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2500}
2501
2502TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2503 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2504 SetFactoryDtlsSrtp();
2505 constraints_.reset(new FakeConstraints());
2506 constraints_->AddOptional(
2507 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2508 InitWithDtls(false);
2509
2510 // Create remote offer with SCTP.
2511 cricket::MediaSessionOptions options;
2512 options.data_channel_type = cricket::DCT_SCTP;
2513 JsepSessionDescription* offer =
2514 CreateRemoteOffer(options, cricket::SEC_ENABLED);
2515 SetRemoteDescriptionWithoutError(offer);
2516
2517 // Verifies the answer contains SCTP.
2518 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2519 EXPECT_TRUE(answer != NULL);
2520 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
2521 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002522}
2523
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002524TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2525 constraints_.reset(new FakeConstraints());
2526 constraints_->AddOptional(
2527 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002528 constraints_->AddOptional(
2529 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
2530 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002531
2532 SetLocalDescriptionWithDataChannel();
2533 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2534}
2535
2536TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2537 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2538
2539 constraints_.reset(new FakeConstraints());
2540 constraints_->AddOptional(
2541 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002542 InitWithDtls(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002543
2544 SetLocalDescriptionWithDataChannel();
2545 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2546}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002547
2548// Verifies that CreateOffer succeeds when CreateOffer is called before async
2549// identity generation is finished.
2550TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
2551 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002552 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002553
2554 EXPECT_TRUE(session_->waiting_for_identity());
2555 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2556 EXPECT_TRUE(offer != NULL);
2557}
2558
2559// Verifies that CreateAnswer succeeds when CreateOffer is called before async
2560// identity generation is finished.
2561TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
2562 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002563 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002564
2565 cricket::MediaSessionOptions options;
2566 scoped_ptr<JsepSessionDescription> offer(
2567 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
2568 ASSERT_TRUE(offer.get() != NULL);
2569 SetRemoteDescriptionWithoutError(offer.release());
2570
2571 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2572 EXPECT_TRUE(answer != NULL);
2573}
2574
2575// Verifies that CreateOffer succeeds when CreateOffer is called after async
2576// identity generation is finished.
2577TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
2578 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002579 InitWithDtls(false);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002580
2581 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2582 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2583 EXPECT_TRUE(offer != NULL);
2584}
2585
2586// Verifies that CreateOffer fails when CreateOffer is called after async
2587// identity generation fails.
2588TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
2589 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00002590 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002591
2592 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2593 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2594 EXPECT_TRUE(offer == NULL);
2595}
2596
2597// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
2598// before async identity generation is finished.
2599TEST_F(WebRtcSessionTest,
2600 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
2601 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2602 VerifyMultipleAsyncCreateDescription(
2603 true, CreateSessionDescriptionRequest::kOffer);
2604}
2605
2606// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
2607// before async identity generation fails.
2608TEST_F(WebRtcSessionTest,
2609 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
2610 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2611 VerifyMultipleAsyncCreateDescription(
2612 false, CreateSessionDescriptionRequest::kOffer);
2613}
2614
2615// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
2616// before async identity generation is finished.
2617TEST_F(WebRtcSessionTest,
2618 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
2619 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2620 VerifyMultipleAsyncCreateDescription(
2621 true, CreateSessionDescriptionRequest::kAnswer);
2622}
2623
2624// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
2625// before async identity generation fails.
2626TEST_F(WebRtcSessionTest,
2627 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
2628 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2629 VerifyMultipleAsyncCreateDescription(
2630 false, CreateSessionDescriptionRequest::kAnswer);
2631}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002632// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
2633// currently fails because upon disconnection and reconnection OnIceComplete is
2634// called more than once without returning to IceGatheringGathering.