blob: b7464935bab118ec881ba2429332ec30f1166662 [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"
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000045#include "talk/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046#include "talk/base/sslstreamadapter.h"
47#include "talk/base/stringutils.h"
48#include "talk/base/thread.h"
49#include "talk/base/virtualsocketserver.h"
50#include "talk/media/base/fakemediaengine.h"
51#include "talk/media/base/fakevideorenderer.h"
52#include "talk/media/base/mediachannel.h"
53#include "talk/media/devices/fakedevicemanager.h"
54#include "talk/p2p/base/stunserver.h"
55#include "talk/p2p/base/teststunserver.h"
buildbot@webrtc.org41451d42014-05-03 05:39:45 +000056#include "talk/p2p/base/testturnserver.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057#include "talk/p2p/client/basicportallocator.h"
58#include "talk/session/media/channelmanager.h"
59#include "talk/session/media/mediasession.h"
60
61#define MAYBE_SKIP_TEST(feature) \
62 if (!(feature())) { \
63 LOG(LS_INFO) << "Feature disabled... skipping"; \
64 return; \
65 }
66
67using cricket::BaseSession;
68using cricket::DF_PLAY;
69using cricket::DF_SEND;
70using cricket::FakeVoiceMediaChannel;
71using cricket::NS_GINGLE_P2P;
72using cricket::NS_JINGLE_ICE_UDP;
73using cricket::TransportInfo;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074using talk_base::SocketAddress;
75using talk_base::scoped_ptr;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +000076using talk_base::Thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000078using webrtc::CreateSessionDescriptionObserver;
79using webrtc::CreateSessionDescriptionRequest;
80using webrtc::DTLSIdentityRequestObserver;
81using webrtc::DTLSIdentityServiceInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082using webrtc::FakeConstraints;
83using webrtc::IceCandidateCollection;
84using webrtc::JsepIceCandidate;
85using webrtc::JsepSessionDescription;
wu@webrtc.org97077a32013-10-25 21:18:33 +000086using webrtc::PeerConnectionFactoryInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::PeerConnectionInterface;
88using webrtc::SessionDescriptionInterface;
89using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000090using webrtc::WebRtcSession;
wu@webrtc.org364f2042013-11-20 21:49:41 +000091using webrtc::kBundleWithoutRtcpMux;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000092using webrtc::kCreateChannelFailed;
93using webrtc::kInvalidSdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094using webrtc::kMlineMismatch;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000095using webrtc::kPushDownTDFailed;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000096using webrtc::kSdpWithoutIceUfragPwd;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000097using webrtc::kSdpWithoutDtlsFingerprint;
98using webrtc::kSdpWithoutSdesCrypto;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099using webrtc::kSessionError;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000100using webrtc::kSessionErrorDesc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101
wu@webrtc.org364f2042013-11-20 21:49:41 +0000102static const int kClientAddrPort = 0;
103static const char kClientAddrHost1[] = "11.11.11.11";
104static const char kClientAddrHost2[] = "22.22.22.22";
105static const char kStunAddrHost[] = "99.99.99.1";
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000106static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
107static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0);
108static const char kTurnUsername[] = "test";
109static const char kTurnPassword[] = "test";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110
111static const char kSessionVersion[] = "1";
112
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113// Media index of candidates belonging to the first media content.
114static const int kMediaContentIndex0 = 0;
115static const char kMediaContentName0[] = "audio";
116
117// Media index of candidates belonging to the second media content.
118static const int kMediaContentIndex1 = 1;
119static const char kMediaContentName1[] = "video";
120
121static const int kIceCandidatesTimeout = 10000;
122
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000123static const char kFakeDtlsFingerprint[] =
124 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
125 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
126
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127// Add some extra |newlines| to the |message| after |line|.
128static void InjectAfter(const std::string& line,
129 const std::string& newlines,
130 std::string* message) {
131 const std::string tmp = line + newlines;
132 talk_base::replace_substrs(line.c_str(), line.length(),
133 tmp.c_str(), tmp.length(), message);
134}
135
136class MockIceObserver : public webrtc::IceObserver {
137 public:
138 MockIceObserver()
139 : oncandidatesready_(false),
140 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
141 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
142 }
143
144 virtual void OnIceConnectionChange(
145 PeerConnectionInterface::IceConnectionState new_state) {
146 ice_connection_state_ = new_state;
147 }
148 virtual void OnIceGatheringChange(
149 PeerConnectionInterface::IceGatheringState new_state) {
150 // We can never transition back to "new".
151 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
152 ice_gathering_state_ = new_state;
153
154 // oncandidatesready_ really means "ICE gathering is complete".
155 // This if statement ensures that this value remains correct when we
156 // transition from kIceGatheringComplete to kIceGatheringGathering.
157 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
158 oncandidatesready_ = false;
159 }
160 }
161
162 // Found a new candidate.
163 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000164 switch (candidate->sdp_mline_index()) {
165 case kMediaContentIndex0:
166 mline_0_candidates_.push_back(candidate->candidate());
167 break;
168 case kMediaContentIndex1:
169 mline_1_candidates_.push_back(candidate->candidate());
170 break;
171 default:
172 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000173 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000174
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175 // The ICE gathering state should always be Gathering when a candidate is
176 // received (or possibly Completed in the case of the final candidate).
177 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
178 }
179
180 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
181 virtual void OnIceComplete() {
182 EXPECT_FALSE(oncandidatesready_);
183 oncandidatesready_ = true;
184
185 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
186 // be called approximately simultaneously. For ease of testing, this
187 // check additionally requires that they be called in the above order.
188 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
189 ice_gathering_state_);
190 }
191
192 bool oncandidatesready_;
193 std::vector<cricket::Candidate> mline_0_candidates_;
194 std::vector<cricket::Candidate> mline_1_candidates_;
195 PeerConnectionInterface::IceConnectionState ice_connection_state_;
196 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
197};
198
199class WebRtcSessionForTest : public webrtc::WebRtcSession {
200 public:
201 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
202 talk_base::Thread* signaling_thread,
203 talk_base::Thread* worker_thread,
204 cricket::PortAllocator* port_allocator,
205 webrtc::IceObserver* ice_observer,
206 webrtc::MediaStreamSignaling* mediastream_signaling)
207 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
208 mediastream_signaling) {
209 RegisterIceObserver(ice_observer);
210 }
211 virtual ~WebRtcSessionForTest() {}
212
213 using cricket::BaseSession::GetTransportProxy;
214 using webrtc::WebRtcSession::SetAudioPlayout;
215 using webrtc::WebRtcSession::SetAudioSend;
216 using webrtc::WebRtcSession::SetCaptureDevice;
217 using webrtc::WebRtcSession::SetVideoPlayout;
218 using webrtc::WebRtcSession::SetVideoSend;
219};
220
wu@webrtc.org91053e72013-08-10 07:18:04 +0000221class WebRtcSessionCreateSDPObserverForTest
222 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000224 enum State {
225 kInit,
226 kFailed,
227 kSucceeded,
228 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000229 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000230
231 // CreateSessionDescriptionObserver implementation.
232 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000233 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000234 state_ = kSucceeded;
235 }
236 virtual void OnFailure(const std::string& error) {
237 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238 }
239
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000240 SessionDescriptionInterface* description() { return description_.get(); }
241
242 SessionDescriptionInterface* ReleaseDescription() {
243 return description_.release();
244 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000245
wu@webrtc.org91053e72013-08-10 07:18:04 +0000246 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000247
wu@webrtc.org91053e72013-08-10 07:18:04 +0000248 protected:
249 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000250
251 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000252 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000253 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000254};
255
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000256class FakeAudioRenderer : public cricket::AudioRenderer {
257 public:
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000258 FakeAudioRenderer() : channel_id_(-1), sink_(NULL) {}
259 virtual ~FakeAudioRenderer() {
260 if (sink_)
261 sink_->OnClose();
262 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000263
264 virtual void AddChannel(int channel_id) OVERRIDE {
265 ASSERT(channel_id_ == -1);
266 channel_id_ = channel_id;
267 }
268 virtual void RemoveChannel(int channel_id) OVERRIDE {
269 ASSERT(channel_id == channel_id_);
270 channel_id_ = -1;
271 }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000272 virtual void SetSink(Sink* sink) OVERRIDE {
273 sink_ = sink;
274 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000275
276 int channel_id() const { return channel_id_; }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000277 cricket::AudioRenderer::Sink* sink() const { return sink_; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000278 private:
279 int channel_id_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000280 cricket::AudioRenderer::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000281};
282
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283class WebRtcSessionTest : public testing::Test {
284 protected:
285 // TODO Investigate why ChannelManager crashes, if it's created
286 // after stun_server.
287 WebRtcSessionTest()
288 : media_engine_(new cricket::FakeMediaEngine()),
289 data_engine_(new cricket::FakeDataEngine()),
290 device_manager_(new cricket::FakeDeviceManager()),
291 channel_manager_(new cricket::ChannelManager(
292 media_engine_, data_engine_, device_manager_,
293 new cricket::CaptureManager(), talk_base::Thread::Current())),
294 tdesc_factory_(new cricket::TransportDescriptionFactory()),
295 desc_factory_(new cricket::MediaSessionDescriptionFactory(
296 channel_manager_.get(), tdesc_factory_.get())),
297 pss_(new talk_base::PhysicalSocketServer),
298 vss_(new talk_base::VirtualSocketServer(pss_.get())),
299 fss_(new talk_base::FirewallSocketServer(vss_.get())),
300 ss_scope_(fss_.get()),
wu@webrtc.org364f2042013-11-20 21:49:41 +0000301 stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
302 cricket::STUN_SERVER_PORT)),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000303 stun_server_(Thread::Current(), stun_socket_addr_),
304 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
305 allocator_(new cricket::BasicPortAllocator(
306 &network_manager_, stun_socket_addr_,
307 SocketAddress(), SocketAddress(), SocketAddress())),
308 mediastream_signaling_(channel_manager_.get()),
309 ice_type_(PeerConnectionInterface::kAll) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000310 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000311 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312 cricket::PORTALLOCATOR_DISABLE_RELAY |
313 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
314 EXPECT_TRUE(channel_manager_->Init());
315 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000316 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317 }
318
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000319 static void SetUpTestCase() {
320 talk_base::InitializeSSL();
321 }
322
323 static void TearDownTestCase() {
324 talk_base::CleanupSSL();
325 }
326
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327 void AddInterface(const SocketAddress& addr) {
328 network_manager_.AddInterface(addr);
329 }
330
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000331 void SetIceTransportType(PeerConnectionInterface::IceTransportsType type) {
332 ice_type_ = type;
333 }
334
wu@webrtc.org91053e72013-08-10 07:18:04 +0000335 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000336 ASSERT_TRUE(session_.get() == NULL);
337 session_.reset(new WebRtcSessionForTest(
338 channel_manager_.get(), talk_base::Thread::Current(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000339 talk_base::Thread::Current(), allocator_.get(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000340 &observer_,
341 &mediastream_signaling_));
342
343 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
344 observer_.ice_connection_state_);
345 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
346 observer_.ice_gathering_state_);
347
wu@webrtc.org97077a32013-10-25 21:18:33 +0000348 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000349 identity_service, ice_type_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350 }
351
352 void InitWithDtmfCodec() {
353 // Add kTelephoneEventCodec for dtmf test.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000354 const cricket::AudioCodec kTelephoneEventCodec(
355 106, "telephone-event", 8000, 0, 1, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 std::vector<cricket::AudioCodec> codecs;
357 codecs.push_back(kTelephoneEventCodec);
358 media_engine_->SetAudioCodecs(codecs);
359 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000360 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000361 }
362
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000363 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000364 FakeIdentityService* identity_service = new FakeIdentityService();
365 identity_service->set_should_fail(identity_request_should_fail);
366 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367 }
368
369 // Creates a local offer and applies it. Starts ice.
370 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
371 // to decide which streams to create.
372 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000373 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000374 SetLocalDescriptionWithoutError(offer);
375 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
376 observer_.ice_gathering_state_,
377 kIceCandidatesTimeout);
378 }
379
wu@webrtc.org91053e72013-08-10 07:18:04 +0000380 SessionDescriptionInterface* CreateOffer(
381 const webrtc::MediaConstraintsInterface* constraints) {
382 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
383 observer = new WebRtcSessionCreateSDPObserverForTest();
384 session_->CreateOffer(observer, constraints);
385 EXPECT_TRUE_WAIT(
386 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000387 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000388 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000389 }
390
391 SessionDescriptionInterface* CreateAnswer(
392 const webrtc::MediaConstraintsInterface* constraints) {
393 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
394 = new WebRtcSessionCreateSDPObserverForTest();
395 session_->CreateAnswer(observer, constraints);
396 EXPECT_TRUE_WAIT(
397 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000398 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000399 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000400 }
401
wu@webrtc.org364f2042013-11-20 21:49:41 +0000402 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000403 return (session_->voice_channel() != NULL &&
404 session_->video_channel() != NULL);
405 }
406
wu@webrtc.org364f2042013-11-20 21:49:41 +0000407 void CheckTransportChannels() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000408 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
409 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
410 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
411 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
412 }
413
414 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
415 ASSERT_TRUE(session_.get() != NULL);
416 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
417 ASSERT_TRUE(content != NULL);
418 const cricket::AudioContentDescription* audio_content =
419 static_cast<const cricket::AudioContentDescription*>(
420 content->description);
421 ASSERT_TRUE(audio_content != NULL);
422 ASSERT_EQ(1U, audio_content->cryptos().size());
423 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
424 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
425 audio_content->cryptos()[0].cipher_suite);
426 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
427 audio_content->protocol());
428
429 content = cricket::GetFirstVideoContent(sdp);
430 ASSERT_TRUE(content != NULL);
431 const cricket::VideoContentDescription* video_content =
432 static_cast<const cricket::VideoContentDescription*>(
433 content->description);
434 ASSERT_TRUE(video_content != NULL);
435 ASSERT_EQ(1U, video_content->cryptos().size());
436 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
437 video_content->cryptos()[0].cipher_suite);
438 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
439 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
440 video_content->protocol());
441 }
442
443 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
444 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
445 ASSERT_TRUE(content != NULL);
446 const cricket::AudioContentDescription* audio_content =
447 static_cast<const cricket::AudioContentDescription*>(
448 content->description);
449 ASSERT_TRUE(audio_content != NULL);
450 ASSERT_EQ(0U, audio_content->cryptos().size());
451
452 content = cricket::GetFirstVideoContent(sdp);
453 ASSERT_TRUE(content != NULL);
454 const cricket::VideoContentDescription* video_content =
455 static_cast<const cricket::VideoContentDescription*>(
456 content->description);
457 ASSERT_TRUE(video_content != NULL);
458 ASSERT_EQ(0U, video_content->cryptos().size());
459
460 if (dtls) {
461 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
462 audio_content->protocol());
463 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
464 video_content->protocol());
465 } else {
466 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
467 audio_content->protocol());
468 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
469 video_content->protocol());
470 }
471 }
472
473 // Set the internal fake description factories to do DTLS-SRTP.
474 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000475 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000476 std::string identity_name = "WebRTC" +
477 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000478 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
479 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000480 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
481 }
482
483 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
484 bool expected) {
485 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
486 ASSERT_TRUE(audio != NULL);
487 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 const TransportInfo* video = sdp->GetTransportInfoByName("video");
489 ASSERT_TRUE(video != NULL);
490 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 }
492
493 void VerifyAnswerFromNonCryptoOffer() {
494 // Create a SDP without Crypto.
495 cricket::MediaSessionOptions options;
496 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000497 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000498 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000499 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000500 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000501 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
502 offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000503 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 // Answer should be NULL as no crypto params in offer.
505 ASSERT_TRUE(answer == NULL);
506 }
507
508 void VerifyAnswerFromCryptoOffer() {
509 cricket::MediaSessionOptions options;
510 options.has_video = true;
511 options.bundle_enabled = true;
512 scoped_ptr<JsepSessionDescription> offer(
513 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
514 ASSERT_TRUE(offer.get() != NULL);
515 VerifyCryptoParams(offer->description());
516 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000517 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 ASSERT_TRUE(answer.get() != NULL);
519 VerifyCryptoParams(answer->description());
520 }
521
522 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
523 const cricket::SessionDescription* desc2,
524 bool expect_equal) {
525 if (desc1->contents().size() != desc2->contents().size()) {
526 EXPECT_FALSE(expect_equal);
527 return;
528 }
529
530 const cricket::ContentInfos& contents = desc1->contents();
531 cricket::ContentInfos::const_iterator it = contents.begin();
532
533 for (; it != contents.end(); ++it) {
534 const cricket::TransportDescription* transport_desc1 =
535 desc1->GetTransportDescriptionByName(it->name);
536 const cricket::TransportDescription* transport_desc2 =
537 desc2->GetTransportDescriptionByName(it->name);
538 if (!transport_desc1 || !transport_desc2) {
539 EXPECT_FALSE(expect_equal);
540 return;
541 }
542 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
543 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
544 EXPECT_FALSE(expect_equal);
545 return;
546 }
547 }
548 EXPECT_TRUE(expect_equal);
549 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000550
551 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
552 std::string *sdp) {
553 const cricket::SessionDescription* desc = current_desc->description();
554 EXPECT_TRUE(current_desc->ToString(sdp));
555
556 const cricket::ContentInfos& contents = desc->contents();
557 cricket::ContentInfos::const_iterator it = contents.begin();
558 // Replace ufrag and pwd lines with empty strings.
559 for (; it != contents.end(); ++it) {
560 const cricket::TransportDescription* transport_desc =
561 desc->GetTransportDescriptionByName(it->name);
562 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
563 + "\r\n";
564 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
565 + "\r\n";
566 talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
567 "", 0,
568 sdp);
569 talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
570 "", 0,
571 sdp);
572 }
573 }
574
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 // Creates a remote offer and and applies it as a remote description,
576 // creates a local answer and applies is as a local description.
577 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
578 // to decide which local and remote streams to create.
579 void CreateAndSetRemoteOfferAndLocalAnswer() {
580 SessionDescriptionInterface* offer = CreateRemoteOffer();
581 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000582 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 SetLocalDescriptionWithoutError(answer);
584 }
585 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
586 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
587 }
588 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
589 BaseSession::State expected_state) {
590 SetLocalDescriptionWithoutError(desc);
591 EXPECT_EQ(expected_state, session_->state());
592 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000593 void SetLocalDescriptionExpectError(const std::string& action,
594 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 SessionDescriptionInterface* desc) {
596 std::string error;
597 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000598 std::string sdp_type = "local ";
599 sdp_type.append(action);
600 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 EXPECT_NE(std::string::npos, error.find(expected_error));
602 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000603 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
604 SessionDescriptionInterface* desc) {
605 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
606 expected_error, desc);
607 }
608 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
609 SessionDescriptionInterface* desc) {
610 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
611 expected_error, desc);
612 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000613 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
614 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
615 }
616 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
617 BaseSession::State expected_state) {
618 SetRemoteDescriptionWithoutError(desc);
619 EXPECT_EQ(expected_state, session_->state());
620 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000621 void SetRemoteDescriptionExpectError(const std::string& action,
622 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000623 SessionDescriptionInterface* desc) {
624 std::string error;
625 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000626 std::string sdp_type = "remote ";
627 sdp_type.append(action);
628 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 EXPECT_NE(std::string::npos, error.find(expected_error));
630 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000631 void SetRemoteDescriptionOfferExpectError(
632 const std::string& expected_error, SessionDescriptionInterface* desc) {
633 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
634 expected_error, desc);
635 }
636 void SetRemoteDescriptionPranswerExpectError(
637 const std::string& expected_error, SessionDescriptionInterface* desc) {
638 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
639 expected_error, desc);
640 }
641 void SetRemoteDescriptionAnswerExpectError(
642 const std::string& expected_error, SessionDescriptionInterface* desc) {
643 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
644 expected_error, desc);
645 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646
647 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
648 SessionDescriptionInterface** nocrypto_answer) {
649 // Create a SDP without Crypto.
650 cricket::MediaSessionOptions options;
651 options.has_video = true;
652 options.bundle_enabled = true;
653 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
654 ASSERT_TRUE(*offer != NULL);
655 VerifyCryptoParams((*offer)->description());
656
657 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
658 cricket::SEC_DISABLED);
659 EXPECT_TRUE(*nocrypto_answer != NULL);
660 }
661
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000662 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
663 SessionDescriptionInterface** nodtls_answer) {
664 cricket::MediaSessionOptions options;
665 options.has_video = true;
666 options.bundle_enabled = true;
667
668 talk_base::scoped_ptr<SessionDescriptionInterface> temp_offer(
669 CreateRemoteOffer(options, cricket::SEC_ENABLED));
670
671 *nodtls_answer =
672 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
673 EXPECT_TRUE(*nodtls_answer != NULL);
674 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
675 VerifyCryptoParams((*nodtls_answer)->description());
676
677 SetFactoryDtlsSrtp();
678 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
679 ASSERT_TRUE(*offer != NULL);
680 VerifyFingerprintStatus((*offer)->description(), true);
681 VerifyCryptoParams((*offer)->description());
682 }
683
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 JsepSessionDescription* CreateRemoteOfferWithVersion(
685 cricket::MediaSessionOptions options,
686 cricket::SecurePolicy secure_policy,
687 const std::string& session_version,
688 const SessionDescriptionInterface* current_desc) {
689 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
690 const cricket::SessionDescription* cricket_desc = NULL;
691 if (current_desc) {
692 cricket_desc = current_desc->description();
693 session_id = current_desc->session_id();
694 }
695
696 desc_factory_->set_secure(secure_policy);
697 JsepSessionDescription* offer(
698 new JsepSessionDescription(JsepSessionDescription::kOffer));
699 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
700 session_id, session_version)) {
701 delete offer;
702 offer = NULL;
703 }
704 return offer;
705 }
706 JsepSessionDescription* CreateRemoteOffer(
707 cricket::MediaSessionOptions options) {
708 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
709 kSessionVersion, NULL);
710 }
711 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000712 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
713 return CreateRemoteOfferWithVersion(
714 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 }
716 JsepSessionDescription* CreateRemoteOffer(
717 cricket::MediaSessionOptions options,
718 const SessionDescriptionInterface* current_desc) {
719 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
720 kSessionVersion, current_desc);
721 }
722
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000723 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
724 const char* sctp_stream_name, int new_port,
725 cricket::MediaSessionOptions options) {
726 options.data_channel_type = cricket::DCT_SCTP;
727 options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel",
728 sctp_stream_name);
729 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
730 }
731
732 // Takes ownership of offer_basis (and deletes it).
733 JsepSessionDescription* ChangeSDPSctpPort(
734 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
735 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
736 // SessionDescription from the mutated string.
737 const char* default_port_str = "5000";
738 char new_port_str[16];
739 talk_base::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
740 std::string offer_str;
741 offer_basis->ToString(&offer_str);
742 talk_base::replace_substrs(default_port_str, strlen(default_port_str),
743 new_port_str, strlen(new_port_str),
744 &offer_str);
745 JsepSessionDescription* offer = new JsepSessionDescription(
746 offer_basis->type());
747 delete offer_basis;
748 offer->Initialize(offer_str, NULL);
749 return offer;
750 }
751
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000752 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
753 // before this function to decide which streams to create.
754 JsepSessionDescription* CreateRemoteOffer() {
755 cricket::MediaSessionOptions options;
756 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
757 return CreateRemoteOffer(options, session_->remote_description());
758 }
759
760 JsepSessionDescription* CreateRemoteAnswer(
761 const SessionDescriptionInterface* offer,
762 cricket::MediaSessionOptions options,
763 cricket::SecurePolicy policy) {
764 desc_factory_->set_secure(policy);
765 const std::string session_id =
766 talk_base::ToString(talk_base::CreateRandomId64());
767 JsepSessionDescription* answer(
768 new JsepSessionDescription(JsepSessionDescription::kAnswer));
769 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
770 options, NULL),
771 session_id, kSessionVersion)) {
772 delete answer;
773 answer = NULL;
774 }
775 return answer;
776 }
777
778 JsepSessionDescription* CreateRemoteAnswer(
779 const SessionDescriptionInterface* offer,
780 cricket::MediaSessionOptions options) {
781 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
782 }
783
784 // Creates an answer session description with streams based on
785 // |mediastream_signaling_|. Call
786 // mediastream_signaling_.UseOptionsWithStreamX() before this function
787 // to decide which streams to create.
788 JsepSessionDescription* CreateRemoteAnswer(
789 const SessionDescriptionInterface* offer) {
790 cricket::MediaSessionOptions options;
791 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
792 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
793 }
794
795 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000796 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000797 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 mediastream_signaling_.SendAudioVideoStream1();
799 FakeConstraints constraints;
800 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000801 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
803 // and answer.
804 SetLocalDescriptionWithoutError(offer);
805
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000806 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
807 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000808 std::string sdp;
809 EXPECT_TRUE(answer->ToString(&sdp));
810
811 size_t expected_candidate_num = 2;
812 if (!rtcp_mux) {
813 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
814 // for rtp and rtcp.
815 expected_candidate_num = 4;
816 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000817 const std::string kRtcpMux = "a=rtcp-mux";
818 const std::string kXRtcpMux = "a=xrtcp-mux";
819 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
820 kXRtcpMux.c_str(), kXRtcpMux.length(),
821 &sdp);
822 }
823
824 SessionDescriptionInterface* new_answer = CreateSessionDescription(
825 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826
827 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000828 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000829 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
830 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
831 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
832 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
833 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
834 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
835 if (bundle) {
836 EXPECT_TRUE(c0.IsEquivalent(c1));
837 } else {
838 EXPECT_FALSE(c0.IsEquivalent(c1));
839 }
840 }
841 }
842 // Tests that we can only send DTMF when the dtmf codec is supported.
843 void TestCanInsertDtmf(bool can) {
844 if (can) {
845 InitWithDtmfCodec();
846 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000847 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848 }
849 mediastream_signaling_.SendAudioVideoStream1();
850 CreateAndSetRemoteOfferAndLocalAnswer();
851 EXPECT_FALSE(session_->CanInsertDtmf(""));
852 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
853 }
854
855 // The method sets up a call from the session to itself, in a loopback
856 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000857 // disconnection, and then a permanent disconnection.
858 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 // by multiple tests with different allocators (e.g. with and without BUNDLE).
860 // While running the call, this method also checks if the session goes through
861 // the correct sequence of ICE states when a connection is established,
862 // broken, and re-established.
863 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000864 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
865 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000866 // The Gathering state should go: New -> Gathering -> Completed.
867 void TestLoopbackCall() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000868 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000869 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000870 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000871 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872
873 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
874 observer_.ice_gathering_state_);
875 SetLocalDescriptionWithoutError(offer);
876 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
877 observer_.ice_connection_state_);
878 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
879 observer_.ice_gathering_state_,
880 kIceCandidatesTimeout);
881 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
882 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
883 observer_.ice_gathering_state_,
884 kIceCandidatesTimeout);
885
886 std::string sdp;
887 offer->ToString(&sdp);
888 SessionDescriptionInterface* desc =
889 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
890 ASSERT_TRUE(desc != NULL);
891 SetRemoteDescriptionWithoutError(desc);
892
893 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
894 observer_.ice_connection_state_,
895 kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +0000896
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000897 // The ice connection state is "Connected" too briefly to catch in a test.
898 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000899 observer_.ice_connection_state_,
900 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901
902 // Adding firewall rule to block ping requests, which should cause
903 // transport channel failure.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000904 fss_->AddRule(false,
905 talk_base::FP_ANY,
906 talk_base::FD_ANY,
907 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000908 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
909 observer_.ice_connection_state_,
910 kIceCandidatesTimeout);
911
912 // Clearing the rules, session should move back to completed state.
913 fss_->ClearRules();
914 // Session is automatically calling OnSignalingReady after creation of
915 // new portallocator session which will allocate new set of candidates.
916
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000917 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 observer_.ice_connection_state_,
919 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000920
921 // Now we block ping requests and wait until the ICE connection transitions
922 // to the Failed state. This will take at least 30 seconds because it must
923 // wait for the Port to timeout.
924 int port_timeout = 30000;
925 fss_->AddRule(false,
926 talk_base::FP_ANY,
927 talk_base::FD_ANY,
928 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
929 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed,
930 observer_.ice_connection_state_,
931 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932 }
933
934 void VerifyTransportType(const std::string& content_name,
935 cricket::TransportProtocol protocol) {
936 const cricket::Transport* transport = session_->GetTransport(content_name);
937 ASSERT_TRUE(transport != NULL);
938 EXPECT_EQ(protocol, transport->protocol());
939 }
940
941 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
942 void AddCNCodecs() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000943 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
944 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
945
946 // Add kCNCodec for dtmf test.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
948 codecs.push_back(kCNCodec1);
949 codecs.push_back(kCNCodec2);
950 media_engine_->SetAudioCodecs(codecs);
951 desc_factory_->set_audio_codecs(codecs);
952 }
953
954 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
955 const cricket::ContentDescription* description = content->description;
956 ASSERT(description != NULL);
957 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000958 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 ASSERT(audio_content_desc != NULL);
960 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
961 if (audio_content_desc->codecs()[i].name == "CN")
962 return false;
963 }
964 return true;
965 }
966
967 void SetLocalDescriptionWithDataChannel() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +0000968 webrtc::InternalDataChannelInit dci;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 dci.reliable = false;
970 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000971 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972 SetLocalDescriptionWithoutError(offer);
973 }
974
wu@webrtc.org91053e72013-08-10 07:18:04 +0000975 void VerifyMultipleAsyncCreateDescription(
976 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000977 InitWithDtls(!success);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000978 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000979 if (type == CreateSessionDescriptionRequest::kAnswer) {
980 cricket::MediaSessionOptions options;
981 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000982 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000983 ASSERT_TRUE(offer.get() != NULL);
984 SetRemoteDescriptionWithoutError(offer.release());
985 }
986
987 const int kNumber = 3;
988 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
989 observers[kNumber];
990 for (int i = 0; i < kNumber; ++i) {
991 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
992 if (type == CreateSessionDescriptionRequest::kOffer) {
993 session_->CreateOffer(observers[i], NULL);
994 } else {
995 session_->CreateAnswer(observers[i], NULL);
996 }
997 }
998
999 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1000 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1001 WebRtcSessionCreateSDPObserverForTest::kFailed;
1002
1003 for (int i = 0; i < kNumber; ++i) {
1004 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1005 if (success) {
1006 EXPECT_TRUE(observers[i]->description() != NULL);
1007 } else {
1008 EXPECT_TRUE(observers[i]->description() == NULL);
1009 }
1010 }
1011 }
1012
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013 cricket::FakeMediaEngine* media_engine_;
1014 cricket::FakeDataEngine* data_engine_;
1015 cricket::FakeDeviceManager* device_manager_;
1016 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
1017 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001018 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001019 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1020 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
1021 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
1022 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
1023 talk_base::SocketServerScope ss_scope_;
wu@webrtc.org364f2042013-11-20 21:49:41 +00001024 talk_base::SocketAddress stun_socket_addr_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001025 cricket::TestStunServer stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001026 cricket::TestTurnServer turn_server_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001027 talk_base::FakeNetworkManager network_manager_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001028 talk_base::scoped_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001029 PeerConnectionFactoryInterface::Options options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030 talk_base::scoped_ptr<FakeConstraints> constraints_;
1031 FakeMediaStreamSignaling mediastream_signaling_;
1032 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
1033 MockIceObserver observer_;
1034 cricket::FakeVideoMediaChannel* video_channel_;
1035 cricket::FakeVoiceMediaChannel* voice_channel_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001036 PeerConnectionInterface::IceTransportsType ice_type_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037};
1038
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
1040 InitWithDtls();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001041 // SDES is disabled when DTLS is on.
1042 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043}
1044
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001045TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001046 Init(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001047 // SDES is required if DTLS is off.
1048 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001049}
1050
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1052 TestSessionCandidatesWithBundleRtcpMux(false, false);
1053}
1054
1055// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1056// with rtcp-mux and/or bundle.
1057TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1058 TestSessionCandidatesWithBundleRtcpMux(false, true);
1059}
1060
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001061TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1062 TestSessionCandidatesWithBundleRtcpMux(true, true);
1063}
1064
1065TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001066 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1067 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001068 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 mediastream_signaling_.SendAudioVideoStream1();
1070 InitiateCall();
1071 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1072 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1073 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1074}
1075
1076TEST_F(WebRtcSessionTest, TestStunError) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001077 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1078 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
1079 fss_->AddRule(false,
1080 talk_base::FP_UDP,
1081 talk_base::FD_ANY,
1082 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001083 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 mediastream_signaling_.SendAudioVideoStream1();
1085 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001086 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1088 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1089 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1090}
1091
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001092TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
1093 Init(NULL);
1094 SessionDescriptionInterface* offer = NULL;
1095 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1096 std::string unknown_action;
1097 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1098 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1099}
1100
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101// Test creating offers and receive answers and make sure the
1102// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001103TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001104 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001105 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001106 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001107 const std::string session_id_orig = offer->session_id();
1108 const std::string session_version_orig = offer->session_version();
1109 SetLocalDescriptionWithoutError(offer);
1110
1111 mediastream_signaling_.SendAudioVideoStream2();
1112 SessionDescriptionInterface* answer =
1113 CreateRemoteAnswer(session_->local_description());
1114 SetRemoteDescriptionWithoutError(answer);
1115
1116 video_channel_ = media_engine_->GetVideoChannel(0);
1117 voice_channel_ = media_engine_->GetVoiceChannel(0);
1118
1119 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1120 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1121
1122 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1123 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1124
1125 ASSERT_EQ(1u, video_channel_->send_streams().size());
1126 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1127 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1128 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1129
1130 // Create new offer without send streams.
1131 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001132 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001133
1134 // Verify the session id is the same and the session version is
1135 // increased.
1136 EXPECT_EQ(session_id_orig, offer->session_id());
1137 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1138 talk_base::FromString<uint64>(offer->session_version()));
1139
1140 SetLocalDescriptionWithoutError(offer);
1141
1142 mediastream_signaling_.SendAudioVideoStream2();
1143 answer = CreateRemoteAnswer(session_->local_description());
1144 SetRemoteDescriptionWithoutError(answer);
1145
1146 EXPECT_EQ(0u, video_channel_->send_streams().size());
1147 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1148
1149 // Make sure the receive streams have not changed.
1150 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1151 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1152 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1153 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1154}
1155
1156// Test receiving offers and creating answers and make sure the
1157// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001158TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001159 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001160 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001161 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001162 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001163 SetRemoteDescriptionWithoutError(offer);
1164
1165 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001166 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001167 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001168 SetLocalDescriptionWithoutError(answer);
1169
1170 const std::string session_id_orig = answer->session_id();
1171 const std::string session_version_orig = answer->session_version();
1172
1173 video_channel_ = media_engine_->GetVideoChannel(0);
1174 voice_channel_ = media_engine_->GetVoiceChannel(0);
1175
1176 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1177 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1178
1179 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1180 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1181
1182 ASSERT_EQ(1u, video_channel_->send_streams().size());
1183 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1184 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1185 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1186
1187 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001188 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001189 SetRemoteDescriptionWithoutError(offer);
1190
1191 // Answer by turning off all send streams.
1192 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001193 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001194
1195 // Verify the session id is the same and the session version is
1196 // increased.
1197 EXPECT_EQ(session_id_orig, answer->session_id());
1198 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1199 talk_base::FromString<uint64>(answer->session_version()));
1200 SetLocalDescriptionWithoutError(answer);
1201
1202 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1203 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1204 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1205 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1206 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1207 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1208
1209 // Make sure we have no send streams.
1210 EXPECT_EQ(0u, video_channel_->send_streams().size());
1211 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1212}
1213
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001214TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
1215 Init(NULL);
1216 media_engine_->set_fail_create_channel(true);
1217
1218 SessionDescriptionInterface* offer = CreateOffer(NULL);
1219 ASSERT_TRUE(offer != NULL);
1220 // SetRemoteDescription and SetLocalDescription will take the ownership of
1221 // the offer.
1222 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
1223 offer = CreateOffer(NULL);
1224 ASSERT_TRUE(offer != NULL);
1225 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1226}
1227
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001228//
1229// Tests for creating/setting SDP under different SDES/DTLS polices:
1230//
1231// --DTLS off and SDES on
1232// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1233// set local/remote offer/answer with crypto --> success
1234// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1235// failure
1236// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1237// failure
1238// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1239// failure
1240//
1241// --DTLS on and SDES off
1242// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1243// set local/remote offer/answer with DTLS fingerprint --> success
1244// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1245// fingerprint --> failure
1246// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1247// --> failure
1248// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1249// --> failure
1250//
1251// --Encryption disabled: DTLS off and SDES off
1252// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1253// answer without SDES or DTLS --> success
1254// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1255// answer without SDES or DTLS --> success
1256//
1257
1258// Test that we return a failure when applying a remote/local offer that doesn't
1259// have cryptos enabled when DTLS is off.
1260TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001261 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 cricket::MediaSessionOptions options;
1263 options.has_video = true;
1264 JsepSessionDescription* offer = CreateRemoteOffer(
1265 options, cricket::SEC_DISABLED);
1266 ASSERT_TRUE(offer != NULL);
1267 VerifyNoCryptoParams(offer->description(), false);
1268 // SetRemoteDescription and SetLocalDescription will take the ownership of
1269 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001270 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1272 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001273 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001274}
1275
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001276// Test that we return a failure when applying a local answer that doesn't have
1277// cryptos enabled when DTLS is off.
1278TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001279 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001280 SessionDescriptionInterface* offer = NULL;
1281 SessionDescriptionInterface* answer = NULL;
1282 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1283 // SetRemoteDescription and SetLocalDescription will take the ownership of
1284 // the offer.
1285 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001286 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001287}
1288
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001289// Test we will return fail when apply an remote answer that doesn't have
1290// crypto enabled when DTLS is off.
1291TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001292 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293 SessionDescriptionInterface* offer = NULL;
1294 SessionDescriptionInterface* answer = NULL;
1295 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1296 // SetRemoteDescription and SetLocalDescription will take the ownership of
1297 // the offer.
1298 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001299 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001300}
1301
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001302// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1303// and that we return an answer with a DTLS fingerprint.
1304TEST_F(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307 InitWithDtls();
1308 SetFactoryDtlsSrtp();
1309 cricket::MediaSessionOptions options;
1310 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001311 JsepSessionDescription* offer =
1312 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001313 ASSERT_TRUE(offer != NULL);
1314 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001315 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316
1317 // SetRemoteDescription will take the ownership of the offer.
1318 SetRemoteDescriptionWithoutError(offer);
1319
1320 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001321 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322 ASSERT_TRUE(answer != NULL);
1323 VerifyFingerprintStatus(answer->description(), true);
1324 // Check that we don't have an a=crypto line in the answer.
1325 VerifyNoCryptoParams(answer->description(), true);
1326
1327 // Now set the local description, which should work, even without a=crypto.
1328 SetLocalDescriptionWithoutError(answer);
1329}
1330
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001331// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1332// and then we accept a remote answer with a DTLS fingerprint successfully.
1333TEST_F(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
1334 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1335 mediastream_signaling_.SendAudioVideoStream1();
1336 InitWithDtls();
1337 SetFactoryDtlsSrtp();
1338
1339 // Verify that we get a crypto fingerprint in the answer.
1340 SessionDescriptionInterface* offer = CreateOffer(NULL);
1341 ASSERT_TRUE(offer != NULL);
1342 VerifyFingerprintStatus(offer->description(), true);
1343 // Check that we don't have an a=crypto line in the offer.
1344 VerifyNoCryptoParams(offer->description(), true);
1345
1346 // Now set the local description, which should work, even without a=crypto.
1347 SetLocalDescriptionWithoutError(offer);
1348
1349 cricket::MediaSessionOptions options;
1350 options.has_video = true;
1351 JsepSessionDescription* answer =
1352 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1353 ASSERT_TRUE(answer != NULL);
1354 VerifyFingerprintStatus(answer->description(), true);
1355 VerifyNoCryptoParams(answer->description(), true);
1356
1357 // SetRemoteDescription will take the ownership of the answer.
1358 SetRemoteDescriptionWithoutError(answer);
1359}
1360
1361// Test that if we support DTLS and the other side didn't offer a fingerprint,
1362// we will fail to set the remote description.
1363TEST_F(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001364 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1365 InitWithDtls();
1366 cricket::MediaSessionOptions options;
1367 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001368 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369 JsepSessionDescription* offer = CreateRemoteOffer(
1370 options, cricket::SEC_REQUIRED);
1371 ASSERT_TRUE(offer != NULL);
1372 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001373 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001374
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001375 // SetRemoteDescription will take the ownership of the offer.
1376 SetRemoteDescriptionOfferExpectError(
1377 kSdpWithoutDtlsFingerprint, offer);
1378
1379 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1380 // SetLocalDescription will take the ownership of the offer.
1381 SetLocalDescriptionOfferExpectError(
1382 kSdpWithoutDtlsFingerprint, offer);
1383}
1384
1385// Test that we return a failure when applying a local answer that doesn't have
1386// a DTLS fingerprint when DTLS is required.
1387TEST_F(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
1388 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1389 InitWithDtls();
1390 SessionDescriptionInterface* offer = NULL;
1391 SessionDescriptionInterface* answer = NULL;
1392 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1393
1394 // SetRemoteDescription and SetLocalDescription will take the ownership of
1395 // the offer and answer.
1396 SetRemoteDescriptionWithoutError(offer);
1397 SetLocalDescriptionAnswerExpectError(
1398 kSdpWithoutDtlsFingerprint, answer);
1399}
1400
1401// Test that we return a failure when applying a remote answer that doesn't have
1402// a DTLS fingerprint when DTLS is required.
1403TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
1404 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1405 InitWithDtls();
1406 SessionDescriptionInterface* offer = CreateOffer(NULL);
1407 cricket::MediaSessionOptions options;
1408 options.has_video = true;
1409 JsepSessionDescription* answer =
1410 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
1411
1412 // SetRemoteDescription and SetLocalDescription will take the ownership of
1413 // the offer and answer.
1414 SetLocalDescriptionWithoutError(offer);
1415 SetRemoteDescriptionAnswerExpectError(
1416 kSdpWithoutDtlsFingerprint, answer);
1417}
1418
1419// Test that we create a local offer without SDES or DTLS and accept a remote
1420// answer without SDES or DTLS when encryption is disabled.
1421TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
1422 mediastream_signaling_.SendAudioVideoStream1();
1423 options_.disable_encryption = true;
1424 InitWithDtls();
1425
1426 // Verify that we get a crypto fingerprint in the answer.
1427 SessionDescriptionInterface* offer = CreateOffer(NULL);
1428 ASSERT_TRUE(offer != NULL);
1429 VerifyFingerprintStatus(offer->description(), false);
1430 // Check that we don't have an a=crypto line in the offer.
1431 VerifyNoCryptoParams(offer->description(), false);
1432
1433 // Now set the local description, which should work, even without a=crypto.
1434 SetLocalDescriptionWithoutError(offer);
1435
1436 cricket::MediaSessionOptions options;
1437 options.has_video = true;
1438 JsepSessionDescription* answer =
1439 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1440 ASSERT_TRUE(answer != NULL);
1441 VerifyFingerprintStatus(answer->description(), false);
1442 VerifyNoCryptoParams(answer->description(), false);
1443
1444 // SetRemoteDescription will take the ownership of the answer.
1445 SetRemoteDescriptionWithoutError(answer);
1446}
1447
1448// Test that we create a local answer without SDES or DTLS and accept a remote
1449// offer without SDES or DTLS when encryption is disabled.
1450TEST_F(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
1451 options_.disable_encryption = true;
1452 InitWithDtls();
1453
1454 cricket::MediaSessionOptions options;
1455 options.has_video = true;
1456 JsepSessionDescription* offer =
1457 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1458 ASSERT_TRUE(offer != NULL);
1459 VerifyFingerprintStatus(offer->description(), false);
1460 VerifyNoCryptoParams(offer->description(), false);
1461
1462 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001463 SetRemoteDescriptionWithoutError(offer);
1464
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001465 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001466 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001467 ASSERT_TRUE(answer != NULL);
1468 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001469 // Check that we don't have an a=crypto line in the answer.
1470 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001471
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001472 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001473 SetLocalDescriptionWithoutError(answer);
1474}
1475
1476TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001477 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001478 mediastream_signaling_.SendNothing();
1479 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001480 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001481 SetLocalDescriptionWithoutError(offer);
1482
1483 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001484 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485 SetLocalDescriptionWithoutError(offer2);
1486}
1487
1488TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001489 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001490 mediastream_signaling_.SendNothing();
1491 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001492 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001493 SetRemoteDescriptionWithoutError(offer);
1494
wu@webrtc.org91053e72013-08-10 07:18:04 +00001495 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496 SetRemoteDescriptionWithoutError(offer2);
1497}
1498
1499TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001500 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001501 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001502 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001503 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001504 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001505 SetRemoteDescriptionOfferExpectError(
1506 "Called in wrong state: STATE_SENTINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001507}
1508
1509TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001510 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001512 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001514 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001515 SetLocalDescriptionOfferExpectError(
1516 "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001517}
1518
1519TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001520 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 mediastream_signaling_.SendNothing();
1522 SessionDescriptionInterface* offer = CreateRemoteOffer();
1523 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1524
1525 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001526 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1528 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1529
1530 mediastream_signaling_.SendAudioVideoStream1();
1531 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001532 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1534
1535 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1536
1537 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001538 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1540}
1541
1542TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001543 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001545 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1547
1548 JsepSessionDescription* pranswer =
1549 CreateRemoteAnswer(session_->local_description());
1550 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1551
1552 SetRemoteDescriptionExpectState(pranswer,
1553 BaseSession::STATE_RECEIVEDPRACCEPT);
1554
1555 mediastream_signaling_.SendAudioVideoStream1();
1556 JsepSessionDescription* pranswer2 =
1557 CreateRemoteAnswer(session_->local_description());
1558 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1559
1560 SetRemoteDescriptionExpectState(pranswer2,
1561 BaseSession::STATE_RECEIVEDPRACCEPT);
1562
1563 mediastream_signaling_.SendAudioVideoStream2();
1564 SessionDescriptionInterface* answer =
1565 CreateRemoteAnswer(session_->local_description());
1566 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1567}
1568
1569TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001570 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 mediastream_signaling_.SendNothing();
1572 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001573 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 SessionDescriptionInterface* answer =
1575 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001576 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1577 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001578}
1579
1580TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001581 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582 mediastream_signaling_.SendNothing();
1583 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001584 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 SessionDescriptionInterface* answer =
1586 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001587 SetRemoteDescriptionAnswerExpectError(
1588 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589}
1590
1591TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001592 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001593 mediastream_signaling_.SendAudioVideoStream1();
1594
1595 cricket::Candidate candidate;
1596 candidate.set_component(1);
1597 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1598
1599 // Fail since we have not set a offer description.
1600 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1601
wu@webrtc.org91053e72013-08-10 07:18:04 +00001602 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603 SetLocalDescriptionWithoutError(offer);
1604 // Candidate should be allowed to add before remote description.
1605 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1606 candidate.set_component(2);
1607 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1608 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1609
1610 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1611 session_->local_description());
1612 SetRemoteDescriptionWithoutError(answer);
1613
1614 // Verifying the candidates are copied properly from internal vector.
1615 const SessionDescriptionInterface* remote_desc =
1616 session_->remote_description();
1617 ASSERT_TRUE(remote_desc != NULL);
1618 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1619 const IceCandidateCollection* candidates =
1620 remote_desc->candidates(kMediaContentIndex0);
1621 ASSERT_EQ(2u, candidates->count());
1622 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1623 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1624 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1625 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1626
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001627 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
1628 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629 candidate.set_component(2);
1630 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1631 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001632 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633
1634 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1635 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1636}
1637
1638// Test that a remote candidate is added to the remote session description and
1639// that it is retained if the remote session description is changed.
1640TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001641 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642 cricket::Candidate candidate1;
1643 candidate1.set_component(1);
1644 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1645 candidate1);
1646 mediastream_signaling_.SendAudioVideoStream1();
1647 CreateAndSetRemoteOfferAndLocalAnswer();
1648
1649 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1650 const SessionDescriptionInterface* remote_desc =
1651 session_->remote_description();
1652 ASSERT_TRUE(remote_desc != NULL);
1653 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1654 const IceCandidateCollection* candidates =
1655 remote_desc->candidates(kMediaContentIndex0);
1656 ASSERT_EQ(1u, candidates->count());
1657 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1658
1659 // Update the RemoteSessionDescription with a new session description and
1660 // a candidate and check that the new remote session description contains both
1661 // candidates.
1662 SessionDescriptionInterface* offer = CreateRemoteOffer();
1663 cricket::Candidate candidate2;
1664 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1665 candidate2);
1666 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1667 SetRemoteDescriptionWithoutError(offer);
1668
1669 remote_desc = session_->remote_description();
1670 ASSERT_TRUE(remote_desc != NULL);
1671 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1672 candidates = remote_desc->candidates(kMediaContentIndex0);
1673 ASSERT_EQ(2u, candidates->count());
1674 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1675 // Username and password have be updated with the TransportInfo of the
1676 // SessionDescription, won't be equal to the original one.
1677 candidate2.set_username(candidates->at(0)->candidate().username());
1678 candidate2.set_password(candidates->at(0)->candidate().password());
1679 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1680 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1681 // No need to verify the username and password.
1682 candidate1.set_username(candidates->at(1)->candidate().username());
1683 candidate1.set_password(candidates->at(1)->candidate().password());
1684 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1685
1686 // Test that the candidate is ignored if we can add the same candidate again.
1687 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1688}
1689
1690// Test that local candidates are added to the local session description and
1691// that they are retained if the local session description is changed.
1692TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001693 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001694 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 mediastream_signaling_.SendAudioVideoStream1();
1696 CreateAndSetRemoteOfferAndLocalAnswer();
1697
1698 const SessionDescriptionInterface* local_desc = session_->local_description();
1699 const IceCandidateCollection* candidates =
1700 local_desc->candidates(kMediaContentIndex0);
1701 ASSERT_TRUE(candidates != NULL);
1702 EXPECT_EQ(0u, candidates->count());
1703
1704 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1705
1706 local_desc = session_->local_description();
1707 candidates = local_desc->candidates(kMediaContentIndex0);
1708 ASSERT_TRUE(candidates != NULL);
1709 EXPECT_LT(0u, candidates->count());
1710 candidates = local_desc->candidates(1);
1711 ASSERT_TRUE(candidates != NULL);
1712 EXPECT_LT(0u, candidates->count());
1713
1714 // Update the session descriptions.
1715 mediastream_signaling_.SendAudioVideoStream1();
1716 CreateAndSetRemoteOfferAndLocalAnswer();
1717
1718 local_desc = session_->local_description();
1719 candidates = local_desc->candidates(kMediaContentIndex0);
1720 ASSERT_TRUE(candidates != NULL);
1721 EXPECT_LT(0u, candidates->count());
1722 candidates = local_desc->candidates(1);
1723 ASSERT_TRUE(candidates != NULL);
1724 EXPECT_LT(0u, candidates->count());
1725}
1726
1727// Test that we can set a remote session description with remote candidates.
1728TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001729 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730
1731 cricket::Candidate candidate1;
1732 candidate1.set_component(1);
1733 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1734 candidate1);
1735 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001736 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737
1738 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1739 SetRemoteDescriptionWithoutError(offer);
1740
1741 const SessionDescriptionInterface* remote_desc =
1742 session_->remote_description();
1743 ASSERT_TRUE(remote_desc != NULL);
1744 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1745 const IceCandidateCollection* candidates =
1746 remote_desc->candidates(kMediaContentIndex0);
1747 ASSERT_EQ(1u, candidates->count());
1748 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1749
wu@webrtc.org91053e72013-08-10 07:18:04 +00001750 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 SetLocalDescriptionWithoutError(answer);
1752}
1753
1754// Test that offers and answers contains ice candidates when Ice candidates have
1755// been gathered.
1756TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001757 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001758 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759 mediastream_signaling_.SendAudioVideoStream1();
1760 // Ice is started but candidates are not provided until SetLocalDescription
1761 // is called.
1762 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1763 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1764 CreateAndSetRemoteOfferAndLocalAnswer();
1765 // Wait until at least one local candidate has been collected.
1766 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1767 kIceCandidatesTimeout);
1768 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1769 kIceCandidatesTimeout);
1770
1771 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001772 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1774 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1775 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1776 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1777
1778 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1779 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001780 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1782 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1783 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1784 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1785 SetLocalDescriptionWithoutError(answer);
1786}
1787
1788// Verifies TransportProxy and media channels are created with content names
1789// present in the SessionDescription.
1790TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001791 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 mediastream_signaling_.SendAudioVideoStream1();
1793 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001794 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001795
1796 // CreateOffer creates session description with the content names "audio" and
1797 // "video". Goal is to modify these content names and verify transport channel
1798 // proxy in the BaseSession, as proxies are created with the content names
1799 // present in SDP.
1800 std::string sdp;
1801 EXPECT_TRUE(offer->ToString(&sdp));
1802 const std::string kAudioMid = "a=mid:audio";
1803 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1804 const std::string kVideoMid = "a=mid:video";
1805 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1806
1807 // Replacing |audio| with |audio_content_name|.
1808 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1809 kAudioMidReplaceStr.c_str(),
1810 kAudioMidReplaceStr.length(),
1811 &sdp);
1812 // Replacing |video| with |video_content_name|.
1813 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1814 kVideoMidReplaceStr.c_str(),
1815 kVideoMidReplaceStr.length(),
1816 &sdp);
1817
1818 SessionDescriptionInterface* modified_offer =
1819 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1820
1821 SetRemoteDescriptionWithoutError(modified_offer);
1822
1823 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001824 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 SetLocalDescriptionWithoutError(answer);
1826
1827 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1828 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1829 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1830 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1831}
1832
1833// Test that an offer contains the correct media content descriptions based on
1834// the send streams when no constraints have been set.
1835TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001836 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001837 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001838 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001839 ASSERT_TRUE(offer != NULL);
1840 const cricket::ContentInfo* content =
1841 cricket::GetFirstAudioContent(offer->description());
1842 EXPECT_TRUE(content != NULL);
1843 content = cricket::GetFirstVideoContent(offer->description());
1844 EXPECT_TRUE(content == NULL);
1845}
1846
1847// Test that an offer contains the correct media content descriptions based on
1848// the send streams when no constraints have been set.
1849TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001850 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001851 // Test Audio only offer.
1852 mediastream_signaling_.UseOptionsAudioOnly();
1853 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001854 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855 const cricket::ContentInfo* content =
1856 cricket::GetFirstAudioContent(offer->description());
1857 EXPECT_TRUE(content != NULL);
1858 content = cricket::GetFirstVideoContent(offer->description());
1859 EXPECT_TRUE(content == NULL);
1860
1861 // Test Audio / Video offer.
1862 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001863 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001864 content = cricket::GetFirstAudioContent(offer->description());
1865 EXPECT_TRUE(content != NULL);
1866 content = cricket::GetFirstVideoContent(offer->description());
1867 EXPECT_TRUE(content != NULL);
1868}
1869
1870// Test that an offer contains no media content descriptions if
1871// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1872TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001873 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001874 webrtc::FakeConstraints constraints_no_receive;
1875 constraints_no_receive.SetMandatoryReceiveAudio(false);
1876 constraints_no_receive.SetMandatoryReceiveVideo(false);
1877
1878 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001879 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 ASSERT_TRUE(offer != NULL);
1881 const cricket::ContentInfo* content =
1882 cricket::GetFirstAudioContent(offer->description());
1883 EXPECT_TRUE(content == NULL);
1884 content = cricket::GetFirstVideoContent(offer->description());
1885 EXPECT_TRUE(content == NULL);
1886}
1887
1888// Test that an offer contains only audio media content descriptions if
1889// kOfferToReceiveAudio constraints are set to true.
1890TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001891 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001892 webrtc::FakeConstraints constraints_audio_only;
1893 constraints_audio_only.SetMandatoryReceiveAudio(true);
1894 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001895 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001896
1897 const cricket::ContentInfo* content =
1898 cricket::GetFirstAudioContent(offer->description());
1899 EXPECT_TRUE(content != NULL);
1900 content = cricket::GetFirstVideoContent(offer->description());
1901 EXPECT_TRUE(content == NULL);
1902}
1903
1904// Test that an offer contains audio and video media content descriptions if
1905// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1906TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001907 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001908 // Test Audio / Video offer.
1909 webrtc::FakeConstraints constraints_audio_video;
1910 constraints_audio_video.SetMandatoryReceiveAudio(true);
1911 constraints_audio_video.SetMandatoryReceiveVideo(true);
1912 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001913 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001914 const cricket::ContentInfo* content =
1915 cricket::GetFirstAudioContent(offer->description());
1916
1917 EXPECT_TRUE(content != NULL);
1918 content = cricket::GetFirstVideoContent(offer->description());
1919 EXPECT_TRUE(content != NULL);
1920
1921 // TODO(perkj): Should the direction be set to SEND_ONLY if
1922 // The constraints is set to not receive audio or video but a track is added?
1923}
1924
1925// Test that an answer can not be created if the last remote description is not
1926// an offer.
1927TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001928 Init(NULL);
1929 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930 SetLocalDescriptionWithoutError(offer);
1931 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1932 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001933 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001934}
1935
1936// Test that an answer contains the correct media content descriptions when no
1937// constraints have been set.
1938TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001939 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940 // Create a remote offer with audio and video content.
1941 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1942 SetRemoteDescriptionWithoutError(offer.release());
1943 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001944 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001945 const cricket::ContentInfo* content =
1946 cricket::GetFirstAudioContent(answer->description());
1947 ASSERT_TRUE(content != NULL);
1948 EXPECT_FALSE(content->rejected);
1949
1950 content = cricket::GetFirstVideoContent(answer->description());
1951 ASSERT_TRUE(content != NULL);
1952 EXPECT_FALSE(content->rejected);
1953}
1954
1955// Test that an answer contains the correct media content descriptions when no
1956// constraints have been set and the offer only contain audio.
1957TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001958 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001959 // Create a remote offer with audio only.
1960 cricket::MediaSessionOptions options;
1961 options.has_audio = true;
1962 options.has_video = false;
1963 talk_base::scoped_ptr<JsepSessionDescription> offer(
1964 CreateRemoteOffer(options));
1965 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1966 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1967
1968 SetRemoteDescriptionWithoutError(offer.release());
1969 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001970 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001971 const cricket::ContentInfo* content =
1972 cricket::GetFirstAudioContent(answer->description());
1973 ASSERT_TRUE(content != NULL);
1974 EXPECT_FALSE(content->rejected);
1975
1976 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1977}
1978
1979// Test that an answer contains the correct media content descriptions when no
1980// constraints have been set.
1981TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001982 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 // Create a remote offer with audio and video content.
1984 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1985 SetRemoteDescriptionWithoutError(offer.release());
1986 // Test with a stream with tracks.
1987 mediastream_signaling_.SendAudioVideoStream1();
1988 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001989 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001990 const cricket::ContentInfo* content =
1991 cricket::GetFirstAudioContent(answer->description());
1992 ASSERT_TRUE(content != NULL);
1993 EXPECT_FALSE(content->rejected);
1994
1995 content = cricket::GetFirstVideoContent(answer->description());
1996 ASSERT_TRUE(content != NULL);
1997 EXPECT_FALSE(content->rejected);
1998}
1999
2000// Test that an answer contains the correct media content descriptions when
2001// constraints have been set but no stream is sent.
2002TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002003 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 // Create a remote offer with audio and video content.
2005 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2006 SetRemoteDescriptionWithoutError(offer.release());
2007
2008 webrtc::FakeConstraints constraints_no_receive;
2009 constraints_no_receive.SetMandatoryReceiveAudio(false);
2010 constraints_no_receive.SetMandatoryReceiveVideo(false);
2011
2012 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002013 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002014 const cricket::ContentInfo* content =
2015 cricket::GetFirstAudioContent(answer->description());
2016 ASSERT_TRUE(content != NULL);
2017 EXPECT_TRUE(content->rejected);
2018
2019 content = cricket::GetFirstVideoContent(answer->description());
2020 ASSERT_TRUE(content != NULL);
2021 EXPECT_TRUE(content->rejected);
2022}
2023
2024// Test that an answer contains the correct media content descriptions when
2025// constraints have been set and streams are sent.
2026TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002027 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028 // Create a remote offer with audio and video content.
2029 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2030 SetRemoteDescriptionWithoutError(offer.release());
2031
2032 webrtc::FakeConstraints constraints_no_receive;
2033 constraints_no_receive.SetMandatoryReceiveAudio(false);
2034 constraints_no_receive.SetMandatoryReceiveVideo(false);
2035
2036 // Test with a stream with tracks.
2037 mediastream_signaling_.SendAudioVideoStream1();
2038 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002039 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040
2041 // TODO(perkj): Should the direction be set to SEND_ONLY?
2042 const cricket::ContentInfo* content =
2043 cricket::GetFirstAudioContent(answer->description());
2044 ASSERT_TRUE(content != NULL);
2045 EXPECT_FALSE(content->rejected);
2046
2047 // TODO(perkj): Should the direction be set to SEND_ONLY?
2048 content = cricket::GetFirstVideoContent(answer->description());
2049 ASSERT_TRUE(content != NULL);
2050 EXPECT_FALSE(content->rejected);
2051}
2052
2053TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2054 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002055 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056 webrtc::FakeConstraints constraints;
2057 constraints.SetOptionalVAD(false);
2058 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002059 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 const cricket::ContentInfo* content =
2061 cricket::GetFirstAudioContent(offer->description());
2062 EXPECT_TRUE(content != NULL);
2063 EXPECT_TRUE(VerifyNoCNCodecs(content));
2064}
2065
2066TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2067 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002068 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002069 // Create a remote offer with audio and video content.
2070 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2071 SetRemoteDescriptionWithoutError(offer.release());
2072
2073 webrtc::FakeConstraints constraints;
2074 constraints.SetOptionalVAD(false);
2075 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002076 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 const cricket::ContentInfo* content =
2078 cricket::GetFirstAudioContent(answer->description());
2079 ASSERT_TRUE(content != NULL);
2080 EXPECT_TRUE(VerifyNoCNCodecs(content));
2081}
2082
2083// This test verifies the call setup when remote answer with audio only and
2084// later updates with video.
2085TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002086 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002087 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2088 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2089
2090 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002091 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002092
2093 cricket::MediaSessionOptions options;
2094 options.has_video = false;
2095 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2096
2097 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2098 // and answer;
2099 SetLocalDescriptionWithoutError(offer);
2100 SetRemoteDescriptionWithoutError(answer);
2101
2102 video_channel_ = media_engine_->GetVideoChannel(0);
2103 voice_channel_ = media_engine_->GetVoiceChannel(0);
2104
2105 ASSERT_TRUE(video_channel_ == NULL);
2106
2107 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2108 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2109 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2110
2111 // Let the remote end update the session descriptions, with Audio and Video.
2112 mediastream_signaling_.SendAudioVideoStream2();
2113 CreateAndSetRemoteOfferAndLocalAnswer();
2114
2115 video_channel_ = media_engine_->GetVideoChannel(0);
2116 voice_channel_ = media_engine_->GetVoiceChannel(0);
2117
2118 ASSERT_TRUE(video_channel_ != NULL);
2119 ASSERT_TRUE(voice_channel_ != NULL);
2120
2121 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2122 ASSERT_EQ(1u, video_channel_->send_streams().size());
2123 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2124 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2125 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2126 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2127 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2128 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2129
2130 // Change session back to audio only.
2131 mediastream_signaling_.UseOptionsAudioOnly();
2132 CreateAndSetRemoteOfferAndLocalAnswer();
2133
2134 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2135 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2136 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2137 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2138 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2139}
2140
2141// This test verifies the call setup when remote answer with video only and
2142// later updates with audio.
2143TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002144 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2146 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2147 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002148 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002149
2150 cricket::MediaSessionOptions options;
2151 options.has_audio = false;
2152 options.has_video = true;
2153 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2154 offer, options, cricket::SEC_ENABLED);
2155
2156 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2157 // and answer.
2158 SetLocalDescriptionWithoutError(offer);
2159 SetRemoteDescriptionWithoutError(answer);
2160
2161 video_channel_ = media_engine_->GetVideoChannel(0);
2162 voice_channel_ = media_engine_->GetVoiceChannel(0);
2163
2164 ASSERT_TRUE(voice_channel_ == NULL);
2165 ASSERT_TRUE(video_channel_ != NULL);
2166
2167 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2168 ASSERT_EQ(1u, video_channel_->send_streams().size());
2169 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2170
2171 // Update the session descriptions, with Audio and Video.
2172 mediastream_signaling_.SendAudioVideoStream2();
2173 CreateAndSetRemoteOfferAndLocalAnswer();
2174
2175 voice_channel_ = media_engine_->GetVoiceChannel(0);
2176 ASSERT_TRUE(voice_channel_ != NULL);
2177
2178 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2179 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2180 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2181 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2182
2183 // Change session back to video only.
2184 mediastream_signaling_.UseOptionsVideoOnly();
2185 CreateAndSetRemoteOfferAndLocalAnswer();
2186
2187 video_channel_ = media_engine_->GetVideoChannel(0);
2188 voice_channel_ = media_engine_->GetVoiceChannel(0);
2189
2190 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2191 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2192 ASSERT_EQ(1u, video_channel_->send_streams().size());
2193 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2194}
2195
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002197 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198 mediastream_signaling_.SendAudioVideoStream1();
2199 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002200 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002201 VerifyCryptoParams(offer->description());
2202 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002203 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002204 VerifyCryptoParams(answer->description());
2205}
2206
2207TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002208 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002209 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002210 mediastream_signaling_.SendAudioVideoStream1();
2211 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002212 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002213 VerifyNoCryptoParams(offer->description(), false);
2214}
2215
2216TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002217 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 VerifyAnswerFromNonCryptoOffer();
2219}
2220
2221TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002222 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002223 VerifyAnswerFromCryptoOffer();
2224}
2225
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002226// This test verifies that setLocalDescription fails if
2227// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2228TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
2229 Init(NULL);
2230 mediastream_signaling_.SendAudioVideoStream1();
2231 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2232 std::string sdp;
2233 RemoveIceUfragPwdLines(offer.get(), &sdp);
2234 SessionDescriptionInterface* modified_offer =
2235 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002236 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002237}
2238
2239// This test verifies that setRemoteDescription fails if
2240// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2241TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
2242 Init(NULL);
2243 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2244 std::string sdp;
2245 RemoveIceUfragPwdLines(offer.get(), &sdp);
2246 SessionDescriptionInterface* modified_offer =
2247 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002248 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002249}
2250
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002251TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
2252 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
2253 // local description is removed by the application, BUNDLE flag should be
2254 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00002255 Init(NULL);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002256 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2257 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002259 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002260 cricket::SessionDescription* offer_copy =
2261 offer->description()->Copy();
2262 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2263 JsepSessionDescription* modified_offer =
2264 new JsepSessionDescription(JsepSessionDescription::kOffer);
2265 modified_offer->Initialize(offer_copy, "1", "1");
2266
2267 SetLocalDescriptionWithoutError(modified_offer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002268 EXPECT_FALSE(allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002269}
2270
2271TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002272 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002273 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002274 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2275 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 FakeConstraints constraints;
2277 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002278 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002279 SetLocalDescriptionWithoutError(offer);
2280 mediastream_signaling_.SendAudioVideoStream2();
2281 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2282 CreateRemoteAnswer(session_->local_description()));
2283 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2284 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2285 JsepSessionDescription* modified_answer =
2286 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2287 modified_answer->Initialize(answer_copy, "1", "1");
2288 SetRemoteDescriptionWithoutError(modified_answer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002289 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2290 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002291
2292 video_channel_ = media_engine_->GetVideoChannel(0);
2293 voice_channel_ = media_engine_->GetVoiceChannel(0);
2294
2295 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2296 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
2297
2298 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2299 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
2300
2301 ASSERT_EQ(1u, video_channel_->send_streams().size());
2302 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
2303 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2304 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
2305}
2306
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002307// This test verifies that SetLocalDescription and SetRemoteDescription fails
2308// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2309TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002310 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002311 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002312 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2313 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002314 FakeConstraints constraints;
2315 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002316 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002317 std::string offer_str;
2318 offer->ToString(&offer_str);
2319 // Disable rtcp-mux
2320 const std::string rtcp_mux = "rtcp-mux";
2321 const std::string xrtcp_mux = "xrtcp-mux";
2322 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
2323 xrtcp_mux.c_str(), xrtcp_mux.length(),
2324 &offer_str);
2325 JsepSessionDescription *local_offer =
2326 new JsepSessionDescription(JsepSessionDescription::kOffer);
2327 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002328 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002329 JsepSessionDescription *remote_offer =
2330 new JsepSessionDescription(JsepSessionDescription::kOffer);
2331 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002332 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002333 // Trying unmodified SDP.
2334 SetLocalDescriptionWithoutError(offer);
2335}
2336
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002337TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002338 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002339 mediastream_signaling_.SendAudioVideoStream1();
2340 CreateAndSetRemoteOfferAndLocalAnswer();
2341 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2342 ASSERT_TRUE(channel != NULL);
2343 ASSERT_EQ(1u, channel->recv_streams().size());
2344 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2345 double left_vol, right_vol;
2346 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2347 EXPECT_EQ(1, left_vol);
2348 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002349 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2350 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002351 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2352 EXPECT_EQ(0, left_vol);
2353 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002354 EXPECT_EQ(0, renderer->channel_id());
2355 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2357 EXPECT_EQ(1, left_vol);
2358 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002359 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002360}
2361
2362TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002363 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002364 mediastream_signaling_.SendAudioVideoStream1();
2365 CreateAndSetRemoteOfferAndLocalAnswer();
2366 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2367 ASSERT_TRUE(channel != NULL);
2368 ASSERT_EQ(1u, channel->send_streams().size());
2369 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2370 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2371
2372 cricket::AudioOptions options;
2373 options.echo_cancellation.Set(true);
2374
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002375 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2376 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002377 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2378 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002379 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002380 EXPECT_TRUE(renderer->sink() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002381
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002382 // This will trigger SetSink(NULL) to the |renderer|.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002383 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002384 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2385 bool value;
2386 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2387 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002388 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002389 EXPECT_TRUE(renderer->sink() == NULL);
2390}
2391
2392TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) {
2393 Init(NULL);
2394 mediastream_signaling_.SendAudioVideoStream1();
2395 CreateAndSetRemoteOfferAndLocalAnswer();
2396 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2397 ASSERT_TRUE(channel != NULL);
2398 ASSERT_EQ(1u, channel->send_streams().size());
2399 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2400
2401 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2402 cricket::AudioOptions options;
2403 session_->SetAudioSend(send_ssrc, true, options, renderer.get());
2404 EXPECT_TRUE(renderer->sink() != NULL);
2405
2406 // Delete the |renderer| and it will trigger OnClose() to the sink, and this
2407 // will invalidate the |renderer_| pointer in the sink and prevent getting a
2408 // SetSink(NULL) callback afterwards.
2409 renderer.reset();
2410
2411 // This will trigger SetSink(NULL) if no OnClose() callback.
2412 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002413}
2414
2415TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002416 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002417 mediastream_signaling_.SendAudioVideoStream1();
2418 CreateAndSetRemoteOfferAndLocalAnswer();
2419 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2420 ASSERT_TRUE(channel != NULL);
2421 ASSERT_LT(0u, channel->renderers().size());
2422 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2423 ASSERT_EQ(1u, channel->recv_streams().size());
2424 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2425 cricket::FakeVideoRenderer renderer;
2426 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2427 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2428 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2429 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2430}
2431
2432TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002433 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002434 mediastream_signaling_.SendAudioVideoStream1();
2435 CreateAndSetRemoteOfferAndLocalAnswer();
2436 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2437 ASSERT_TRUE(channel != NULL);
2438 ASSERT_EQ(1u, channel->send_streams().size());
2439 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2440 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2441 cricket::VideoOptions* options = NULL;
2442 session_->SetVideoSend(send_ssrc, false, options);
2443 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2444 session_->SetVideoSend(send_ssrc, true, options);
2445 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2446}
2447
2448TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2449 TestCanInsertDtmf(false);
2450}
2451
2452TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2453 TestCanInsertDtmf(true);
2454}
2455
2456TEST_F(WebRtcSessionTest, InsertDtmf) {
2457 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002458 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002459 mediastream_signaling_.SendAudioVideoStream1();
2460 CreateAndSetRemoteOfferAndLocalAnswer();
2461 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2462 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2463
2464 // Insert DTMF
2465 const int expected_flags = DF_SEND;
2466 const int expected_duration = 90;
2467 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2468 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2469 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2470
2471 // Verify
2472 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2473 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2474 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2475 expected_duration, expected_flags));
2476 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2477 expected_duration, expected_flags));
2478 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2479 expected_duration, expected_flags));
2480}
2481
2482// This test verifies the |initiator| flag when session initiates the call.
2483TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002484 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002485 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002486 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002487 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2488 SetLocalDescriptionWithoutError(offer);
2489 EXPECT_TRUE(session_->initiator());
2490 SetRemoteDescriptionWithoutError(answer);
2491 EXPECT_TRUE(session_->initiator());
2492}
2493
2494// This test verifies the |initiator| flag when session receives the call.
2495TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002496 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002497 EXPECT_FALSE(session_->initiator());
2498 SessionDescriptionInterface* offer = CreateRemoteOffer();
2499 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002500 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002501
2502 EXPECT_FALSE(session_->initiator());
2503 SetLocalDescriptionWithoutError(answer);
2504 EXPECT_FALSE(session_->initiator());
2505}
2506
2507// This test verifies the ice protocol type at initiator of the call
2508// if |a=ice-options:google-ice| is present in answer.
2509TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002510 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002511 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002512 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002513 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002514 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002515 SetLocalDescriptionWithoutError(offer);
2516 std::string sdp;
2517 EXPECT_TRUE(answer->ToString(&sdp));
2518 // Adding ice-options to the session level.
2519 InjectAfter("t=0 0\r\n",
2520 "a=ice-options:google-ice\r\n",
2521 &sdp);
2522 SessionDescriptionInterface* answer_with_gice =
2523 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2524 SetRemoteDescriptionWithoutError(answer_with_gice);
2525 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2526 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2527}
2528
2529// This test verifies the ice protocol type at initiator of the call
2530// if ICE RFC5245 is supported in answer.
2531TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002532 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002533 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002534 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002535 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2536 SetLocalDescriptionWithoutError(offer);
2537
2538 SetRemoteDescriptionWithoutError(answer);
2539 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2540 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2541}
2542
2543// This test verifies the ice protocol type at receiver side of the call if
2544// receiver decides to use google-ice.
2545TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002546 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002547 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002548 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002549 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002550 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002551 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002552 std::string sdp;
2553 EXPECT_TRUE(answer->ToString(&sdp));
2554 // Adding ice-options to the session level.
2555 InjectAfter("t=0 0\r\n",
2556 "a=ice-options:google-ice\r\n",
2557 &sdp);
2558 SessionDescriptionInterface* answer_with_gice =
2559 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2560 SetLocalDescriptionWithoutError(answer_with_gice);
2561 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2562 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2563}
2564
2565// This test verifies the ice protocol type at receiver side of the call if
2566// receiver decides to use ice RFC 5245.
2567TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002568 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002569 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002570 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002571 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002572 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002573 SetLocalDescriptionWithoutError(answer);
2574 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2575 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2576}
2577
2578// This test verifies the session state when ICE RFC5245 in offer and
2579// ICE google-ice in answer.
2580TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002581 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002582 mediastream_signaling_.SendAudioVideoStream1();
2583 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002584 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002585 std::string offer_str;
2586 offer->ToString(&offer_str);
2587 // Disable google-ice
2588 const std::string gice_option = "google-ice";
2589 const std::string xgoogle_xice = "xgoogle-xice";
2590 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2591 xgoogle_xice.c_str(), xgoogle_xice.length(),
2592 &offer_str);
2593 JsepSessionDescription *ice_only_offer =
2594 new JsepSessionDescription(JsepSessionDescription::kOffer);
2595 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2596 SetLocalDescriptionWithoutError(ice_only_offer);
2597 std::string original_offer_sdp;
2598 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002599 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002600 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002601 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002602 SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
2603 pranswer_with_gice);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002604 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002605 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002606 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002607 SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
2608 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002609}
2610
2611// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2612TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002613 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002614 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002615 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002616 SetLocalDescriptionWithoutError(offer);
2617 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2618 CreateRemoteAnswer(session_->local_description()));
2619
2620 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2621 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002622 JsepSessionDescription* modified_answer =
2623 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002624
2625 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2626 answer->session_id(),
2627 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002628 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002629
wu@webrtc.org4e393072014-04-07 17:04:35 +00002630 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002631 std::string sdp;
2632 EXPECT_TRUE(answer->ToString(&sdp));
2633 const std::string kAudioMid = "a=mid:audio";
2634 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002635 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2636 kAudioMidReplaceStr.c_str(),
2637 kAudioMidReplaceStr.length(),
2638 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002639 SessionDescriptionInterface* modified_answer1 =
2640 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002641 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002642
wu@webrtc.org4e393072014-04-07 17:04:35 +00002643 // Different media types.
2644 EXPECT_TRUE(answer->ToString(&sdp));
2645 const std::string kAudioMline = "m=audio";
2646 const std::string kAudioMlineReplaceStr = "m=video";
2647 talk_base::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
2648 kAudioMlineReplaceStr.c_str(),
2649 kAudioMlineReplaceStr.length(),
2650 &sdp);
2651 SessionDescriptionInterface* modified_answer2 =
2652 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2653 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
2654
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002655 SetRemoteDescriptionWithoutError(answer.release());
2656}
2657
2658// Verifying remote offer and local answer have matching m-lines as per
2659// RFC 3264.
2660TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002661 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002662 mediastream_signaling_.SendAudioVideoStream1();
2663 SessionDescriptionInterface* offer = CreateRemoteOffer();
2664 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002665 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002666
2667 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2668 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002669 JsepSessionDescription* modified_answer =
2670 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002671
2672 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2673 answer->session_id(),
2674 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002675 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002676 SetLocalDescriptionWithoutError(answer);
2677}
2678
2679// This test verifies that WebRtcSession does not start candidate allocation
2680// before SetLocalDescription is called.
2681TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002682 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002683 mediastream_signaling_.SendAudioVideoStream1();
2684 SessionDescriptionInterface* offer = CreateRemoteOffer();
2685 cricket::Candidate candidate;
2686 candidate.set_component(1);
2687 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2688 candidate);
2689 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2690 cricket::Candidate candidate1;
2691 candidate1.set_component(1);
2692 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2693 candidate1);
2694 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2695 SetRemoteDescriptionWithoutError(offer);
2696 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2697 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2698
2699 // Pump for 1 second and verify that no candidates are generated.
2700 talk_base::Thread::Current()->ProcessMessages(1000);
2701 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2702 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2703
wu@webrtc.org91053e72013-08-10 07:18:04 +00002704 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002705 SetLocalDescriptionWithoutError(answer);
2706 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2707 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2708 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2709}
2710
2711// This test verifies that crypto parameter is updated in local session
2712// description as per security policy set in MediaSessionDescriptionFactory.
2713TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002714 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002715 mediastream_signaling_.SendAudioVideoStream1();
2716 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002717 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002718
2719 // Making sure SetLocalDescription correctly sets crypto value in
2720 // SessionDescription object after de-serialization of sdp string. The value
2721 // will be set as per MediaSessionDescriptionFactory.
2722 std::string offer_str;
2723 offer->ToString(&offer_str);
2724 SessionDescriptionInterface* jsep_offer_str =
2725 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2726 SetLocalDescriptionWithoutError(jsep_offer_str);
2727 EXPECT_TRUE(session_->voice_channel()->secure_required());
2728 EXPECT_TRUE(session_->video_channel()->secure_required());
2729}
2730
2731// This test verifies the crypto parameter when security is disabled.
2732TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002733 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002734 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002735 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002736 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002737 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002738
2739 // Making sure SetLocalDescription correctly sets crypto value in
2740 // SessionDescription object after de-serialization of sdp string. The value
2741 // will be set as per MediaSessionDescriptionFactory.
2742 std::string offer_str;
2743 offer->ToString(&offer_str);
2744 SessionDescriptionInterface *jsep_offer_str =
2745 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2746 SetLocalDescriptionWithoutError(jsep_offer_str);
2747 EXPECT_FALSE(session_->voice_channel()->secure_required());
2748 EXPECT_FALSE(session_->video_channel()->secure_required());
2749}
2750
2751// This test verifies that an answer contains new ufrag and password if an offer
2752// with new ufrag and password is received.
2753TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002754 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002755 cricket::MediaSessionOptions options;
2756 options.has_audio = true;
2757 options.has_video = true;
2758 talk_base::scoped_ptr<JsepSessionDescription> offer(
2759 CreateRemoteOffer(options));
2760 SetRemoteDescriptionWithoutError(offer.release());
2761
2762 mediastream_signaling_.SendAudioVideoStream1();
2763 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002764 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002765 SetLocalDescriptionWithoutError(answer.release());
2766
2767 // Receive an offer with new ufrag and password.
2768 options.transport_options.ice_restart = true;
2769 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002770 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002771 SetRemoteDescriptionWithoutError(updated_offer1.release());
2772
2773 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002774 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002775
2776 CompareIceUfragAndPassword(updated_answer1->description(),
2777 session_->local_description()->description(),
2778 false);
2779
2780 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002781}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002782
wu@webrtc.org91053e72013-08-10 07:18:04 +00002783// This test verifies that an answer contains old ufrag and password if an offer
2784// with old ufrag and password is received.
2785TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2786 Init(NULL);
2787 cricket::MediaSessionOptions options;
2788 options.has_audio = true;
2789 options.has_video = true;
2790 talk_base::scoped_ptr<JsepSessionDescription> offer(
2791 CreateRemoteOffer(options));
2792 SetRemoteDescriptionWithoutError(offer.release());
2793
2794 mediastream_signaling_.SendAudioVideoStream1();
2795 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2796 CreateAnswer(NULL));
2797 SetLocalDescriptionWithoutError(answer.release());
2798
2799 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002800 options.transport_options.ice_restart = false;
2801 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002802 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002803 SetRemoteDescriptionWithoutError(updated_offer2.release());
2804
2805 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002806 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002807
2808 CompareIceUfragAndPassword(updated_answer2->description(),
2809 session_->local_description()->description(),
2810 true);
2811
2812 SetLocalDescriptionWithoutError(updated_answer2.release());
2813}
2814
2815TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002816 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002817 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002818 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002819 const std::string session_id_orig = offer->session_id();
2820 const std::string session_version_orig = offer->session_version();
2821 SetLocalDescriptionWithoutError(offer);
2822
2823 video_channel_ = media_engine_->GetVideoChannel(0);
2824 video_channel_->set_fail_set_send_codecs(true);
2825
2826 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002827 SessionDescriptionInterface* answer =
2828 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002829 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002830}
2831
2832// Runs the loopback call test with BUNDLE and STUN disabled.
2833TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2834 // Lets try with only UDP ports.
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002835 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002836 cricket::PORTALLOCATOR_DISABLE_TCP |
2837 cricket::PORTALLOCATOR_DISABLE_STUN |
2838 cricket::PORTALLOCATOR_DISABLE_RELAY);
2839 TestLoopbackCall();
2840}
2841
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002842// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002843TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002844 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002845 cricket::PORTALLOCATOR_ENABLE_BUNDLE |
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002846 cricket::PORTALLOCATOR_DISABLE_TCP |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002847 cricket::PORTALLOCATOR_DISABLE_RELAY);
2848 TestLoopbackCall();
2849}
2850
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002851TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002852 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002853 cricket::MediaSessionOptions options;
2854 options.has_audio = true;
2855 options.has_video = true;
2856
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002857 cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
2858 std::string error_code_str = "ERROR_CONTENT";
2859 std::string error_desc = "Fake session error description.";
2860 session_->SetError(error_code, error_desc);
2861
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002862 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2863 SessionDescriptionInterface* answer =
2864 CreateRemoteAnswer(offer, options);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002865
2866 std::string action;
2867 std::ostringstream session_error_msg;
2868 session_error_msg << kSessionError << error_code_str << ". ";
2869 session_error_msg << kSessionErrorDesc << error_desc << ".";
2870 SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
2871 SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002872}
2873
2874TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2875 constraints_.reset(new FakeConstraints());
2876 constraints_->AddOptional(
2877 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002878 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002879
2880 SetLocalDescriptionWithDataChannel();
2881 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2882}
2883
2884TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2885 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2886
2887 constraints_.reset(new FakeConstraints());
2888 constraints_->AddOptional(
2889 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org97077a32013-10-25 21:18:33 +00002890 options_.disable_sctp_data_channels = false;
2891
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002892 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002893
2894 SetLocalDescriptionWithDataChannel();
2895 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2896}
2897
wu@webrtc.org967bfff2013-09-19 05:49:50 +00002898TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2899 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2900
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002901 InitWithDtls();
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002902
2903 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2904 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002905 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2906}
2907
2908TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2909 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2910 SetFactoryDtlsSrtp();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002911 InitWithDtls();
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002912
2913 // Create remote offer with SCTP.
2914 cricket::MediaSessionOptions options;
2915 options.data_channel_type = cricket::DCT_SCTP;
2916 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002917 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002918 SetRemoteDescriptionWithoutError(offer);
2919
2920 // Verifies the answer contains SCTP.
2921 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2922 EXPECT_TRUE(answer != NULL);
2923 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
2924 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002925}
2926
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002927TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2928 constraints_.reset(new FakeConstraints());
2929 constraints_->AddOptional(
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002930 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002931 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002932
2933 SetLocalDescriptionWithDataChannel();
2934 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2935}
2936
2937TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2938 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2939
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002940 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002941
2942 SetLocalDescriptionWithDataChannel();
2943 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2944}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002945
wu@webrtc.org97077a32013-10-25 21:18:33 +00002946TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
2947 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2948 options_.disable_sctp_data_channels = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002949 InitWithDtls();
wu@webrtc.org97077a32013-10-25 21:18:33 +00002950
2951 SetLocalDescriptionWithDataChannel();
2952 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2953}
2954
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002955TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
2956 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2957 const int new_send_port = 9998;
2958 const int new_recv_port = 7775;
2959
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002960 InitWithDtls();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002961 SetFactoryDtlsSrtp();
2962
2963 // By default, don't actually add the codecs to desc_factory_; they don't
2964 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
2965 // let the session description get parsed. That'll get the proper codecs
2966 // into the stream.
2967 cricket::MediaSessionOptions options;
2968 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
2969 "stream1", new_send_port, options);
2970
2971 // SetRemoteDescription will take the ownership of the offer.
2972 SetRemoteDescriptionWithoutError(offer);
2973
2974 SessionDescriptionInterface* answer = ChangeSDPSctpPort(
2975 new_recv_port, CreateAnswer(NULL));
2976 ASSERT_TRUE(answer != NULL);
2977
2978 // Now set the local description, which'll take ownership of the answer.
2979 SetLocalDescriptionWithoutError(answer);
2980
2981 // TEST PLAN: Set the port number to something new, set it in the SDP,
2982 // and pass it all the way down.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00002983 webrtc::InternalDataChannelInit dci;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002984 dci.reliable = true;
2985 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2986 talk_base::scoped_refptr<webrtc::DataChannel> dc =
2987 session_->CreateDataChannel("datachannel", &dci);
2988
2989 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
2990 int portnum = -1;
2991 ASSERT_TRUE(ch != NULL);
2992 ASSERT_EQ(1UL, ch->send_codecs().size());
2993 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
2994 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
2995 ch->send_codecs()[0].name.c_str()));
2996 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
2997 &portnum));
2998 EXPECT_EQ(new_send_port, portnum);
2999
3000 ASSERT_EQ(1UL, ch->recv_codecs().size());
3001 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
3002 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3003 ch->recv_codecs()[0].name.c_str()));
3004 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
3005 &portnum));
3006 EXPECT_EQ(new_recv_port, portnum);
3007}
3008
wu@webrtc.org91053e72013-08-10 07:18:04 +00003009// Verifies that CreateOffer succeeds when CreateOffer is called before async
3010// identity generation is finished.
3011TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
3012 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003013 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003014
3015 EXPECT_TRUE(session_->waiting_for_identity());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003016 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003017 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3018 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003019 VerifyNoCryptoParams(offer->description(), true);
3020 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003021}
3022
3023// Verifies that CreateAnswer succeeds when CreateOffer is called before async
3024// identity generation is finished.
3025TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
3026 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003027 InitWithDtls();
3028 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003029
3030 cricket::MediaSessionOptions options;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003031 options.has_video = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003032 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003033 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003034 ASSERT_TRUE(offer.get() != NULL);
3035 SetRemoteDescriptionWithoutError(offer.release());
3036
3037 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
3038 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003039 VerifyNoCryptoParams(answer->description(), true);
3040 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003041}
3042
3043// Verifies that CreateOffer succeeds when CreateOffer is called after async
3044// identity generation is finished.
3045TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
3046 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003047 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003048
3049 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3050 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3051 EXPECT_TRUE(offer != NULL);
3052}
3053
3054// Verifies that CreateOffer fails when CreateOffer is called after async
3055// identity generation fails.
3056TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
3057 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00003058 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003059
3060 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3061 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3062 EXPECT_TRUE(offer == NULL);
3063}
3064
3065// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
3066// before async identity generation is finished.
3067TEST_F(WebRtcSessionTest,
3068 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
3069 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3070 VerifyMultipleAsyncCreateDescription(
3071 true, CreateSessionDescriptionRequest::kOffer);
3072}
3073
3074// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
3075// before async identity generation fails.
3076TEST_F(WebRtcSessionTest,
3077 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
3078 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3079 VerifyMultipleAsyncCreateDescription(
3080 false, CreateSessionDescriptionRequest::kOffer);
3081}
3082
3083// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
3084// before async identity generation is finished.
3085TEST_F(WebRtcSessionTest,
3086 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
3087 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3088 VerifyMultipleAsyncCreateDescription(
3089 true, CreateSessionDescriptionRequest::kAnswer);
3090}
3091
3092// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
3093// before async identity generation fails.
3094TEST_F(WebRtcSessionTest,
3095 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
3096 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3097 VerifyMultipleAsyncCreateDescription(
3098 false, CreateSessionDescriptionRequest::kAnswer);
3099}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003100
3101// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
3102// offer has no SDES crypto but only DTLS fingerprint.
3103TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
3104 // Init without DTLS.
3105 Init(NULL);
3106 // Create a remote offer with secured transport disabled.
3107 cricket::MediaSessionOptions options;
3108 JsepSessionDescription* offer(CreateRemoteOffer(
3109 options, cricket::SEC_DISABLED));
3110 // Adds a DTLS fingerprint to the remote offer.
3111 cricket::SessionDescription* sdp = offer->description();
3112 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
3113 ASSERT_TRUE(audio != NULL);
3114 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
3115 audio->description.identity_fingerprint.reset(
3116 talk_base::SSLFingerprint::CreateFromRfc4572(
3117 talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003118 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003119 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003120}
3121
wu@webrtc.orgde305012013-10-31 15:40:38 +00003122// This test verifies DSCP is properly applied on the media channels.
3123TEST_F(WebRtcSessionTest, TestDscpConstraint) {
3124 constraints_.reset(new FakeConstraints());
3125 constraints_->AddOptional(
3126 webrtc::MediaConstraintsInterface::kEnableDscp, true);
3127 Init(NULL);
3128 mediastream_signaling_.SendAudioVideoStream1();
3129 SessionDescriptionInterface* offer = CreateOffer(NULL);
3130
3131 SetLocalDescriptionWithoutError(offer);
3132
3133 video_channel_ = media_engine_->GetVideoChannel(0);
3134 voice_channel_ = media_engine_->GetVoiceChannel(0);
3135
3136 ASSERT_TRUE(video_channel_ != NULL);
3137 ASSERT_TRUE(voice_channel_ != NULL);
3138 cricket::AudioOptions audio_options;
3139 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
3140 cricket::VideoOptions video_options;
3141 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3142 EXPECT_TRUE(audio_options.dscp.IsSet());
3143 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
3144 EXPECT_TRUE(video_options.dscp.IsSet());
3145 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
3146}
3147
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003148TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) {
3149 constraints_.reset(new FakeConstraints());
3150 constraints_->AddOptional(
3151 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
3152 true);
3153 Init(NULL);
3154 mediastream_signaling_.SendAudioVideoStream1();
3155 SessionDescriptionInterface* offer = CreateOffer(NULL);
3156
3157 SetLocalDescriptionWithoutError(offer);
3158
3159 video_channel_ = media_engine_->GetVideoChannel(0);
3160
3161 ASSERT_TRUE(video_channel_ != NULL);
3162 cricket::VideoOptions video_options;
3163 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3164 EXPECT_TRUE(
3165 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false));
3166}
3167
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003168// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
3169// currently fails because upon disconnection and reconnection OnIceComplete is
3170// called more than once without returning to IceGatheringGathering.