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