blob: b6f726b345fe863614168c7c6745c7adfdf76da4 [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
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000127static const char kTooLongIceUfragPwd[] =
128 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
129 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
130 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
131 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag";
132
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133// Add some extra |newlines| to the |message| after |line|.
134static void InjectAfter(const std::string& line,
135 const std::string& newlines,
136 std::string* message) {
137 const std::string tmp = line + newlines;
138 talk_base::replace_substrs(line.c_str(), line.length(),
139 tmp.c_str(), tmp.length(), message);
140}
141
142class MockIceObserver : public webrtc::IceObserver {
143 public:
144 MockIceObserver()
145 : oncandidatesready_(false),
146 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
147 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
148 }
149
150 virtual void OnIceConnectionChange(
151 PeerConnectionInterface::IceConnectionState new_state) {
152 ice_connection_state_ = new_state;
153 }
154 virtual void OnIceGatheringChange(
155 PeerConnectionInterface::IceGatheringState new_state) {
156 // We can never transition back to "new".
157 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
158 ice_gathering_state_ = new_state;
159
160 // oncandidatesready_ really means "ICE gathering is complete".
161 // This if statement ensures that this value remains correct when we
162 // transition from kIceGatheringComplete to kIceGatheringGathering.
163 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
164 oncandidatesready_ = false;
165 }
166 }
167
168 // Found a new candidate.
169 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000170 switch (candidate->sdp_mline_index()) {
171 case kMediaContentIndex0:
172 mline_0_candidates_.push_back(candidate->candidate());
173 break;
174 case kMediaContentIndex1:
175 mline_1_candidates_.push_back(candidate->candidate());
176 break;
177 default:
178 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000180
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 // The ICE gathering state should always be Gathering when a candidate is
182 // received (or possibly Completed in the case of the final candidate).
183 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
184 }
185
186 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
187 virtual void OnIceComplete() {
188 EXPECT_FALSE(oncandidatesready_);
189 oncandidatesready_ = true;
190
191 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
192 // be called approximately simultaneously. For ease of testing, this
193 // check additionally requires that they be called in the above order.
194 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
195 ice_gathering_state_);
196 }
197
198 bool oncandidatesready_;
199 std::vector<cricket::Candidate> mline_0_candidates_;
200 std::vector<cricket::Candidate> mline_1_candidates_;
201 PeerConnectionInterface::IceConnectionState ice_connection_state_;
202 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
203};
204
205class WebRtcSessionForTest : public webrtc::WebRtcSession {
206 public:
207 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
208 talk_base::Thread* signaling_thread,
209 talk_base::Thread* worker_thread,
210 cricket::PortAllocator* port_allocator,
211 webrtc::IceObserver* ice_observer,
212 webrtc::MediaStreamSignaling* mediastream_signaling)
213 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
214 mediastream_signaling) {
215 RegisterIceObserver(ice_observer);
216 }
217 virtual ~WebRtcSessionForTest() {}
218
219 using cricket::BaseSession::GetTransportProxy;
220 using webrtc::WebRtcSession::SetAudioPlayout;
221 using webrtc::WebRtcSession::SetAudioSend;
222 using webrtc::WebRtcSession::SetCaptureDevice;
223 using webrtc::WebRtcSession::SetVideoPlayout;
224 using webrtc::WebRtcSession::SetVideoSend;
225};
226
wu@webrtc.org91053e72013-08-10 07:18:04 +0000227class WebRtcSessionCreateSDPObserverForTest
228 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000230 enum State {
231 kInit,
232 kFailed,
233 kSucceeded,
234 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000235 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000236
237 // CreateSessionDescriptionObserver implementation.
238 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000239 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000240 state_ = kSucceeded;
241 }
242 virtual void OnFailure(const std::string& error) {
243 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000244 }
245
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000246 SessionDescriptionInterface* description() { return description_.get(); }
247
248 SessionDescriptionInterface* ReleaseDescription() {
249 return description_.release();
250 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251
wu@webrtc.org91053e72013-08-10 07:18:04 +0000252 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253
wu@webrtc.org91053e72013-08-10 07:18:04 +0000254 protected:
255 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256
257 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000258 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000259 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000260};
261
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000262class FakeAudioRenderer : public cricket::AudioRenderer {
263 public:
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000264 FakeAudioRenderer() : channel_id_(-1), sink_(NULL) {}
265 virtual ~FakeAudioRenderer() {
266 if (sink_)
267 sink_->OnClose();
268 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000269
270 virtual void AddChannel(int channel_id) OVERRIDE {
271 ASSERT(channel_id_ == -1);
272 channel_id_ = channel_id;
273 }
274 virtual void RemoveChannel(int channel_id) OVERRIDE {
275 ASSERT(channel_id == channel_id_);
276 channel_id_ = -1;
277 }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000278 virtual void SetSink(Sink* sink) OVERRIDE {
279 sink_ = sink;
280 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000281
282 int channel_id() const { return channel_id_; }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000283 cricket::AudioRenderer::Sink* sink() const { return sink_; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000284 private:
285 int channel_id_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000286 cricket::AudioRenderer::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000287};
288
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289class WebRtcSessionTest : public testing::Test {
290 protected:
291 // TODO Investigate why ChannelManager crashes, if it's created
292 // after stun_server.
293 WebRtcSessionTest()
294 : media_engine_(new cricket::FakeMediaEngine()),
295 data_engine_(new cricket::FakeDataEngine()),
296 device_manager_(new cricket::FakeDeviceManager()),
297 channel_manager_(new cricket::ChannelManager(
298 media_engine_, data_engine_, device_manager_,
299 new cricket::CaptureManager(), talk_base::Thread::Current())),
300 tdesc_factory_(new cricket::TransportDescriptionFactory()),
301 desc_factory_(new cricket::MediaSessionDescriptionFactory(
302 channel_manager_.get(), tdesc_factory_.get())),
303 pss_(new talk_base::PhysicalSocketServer),
304 vss_(new talk_base::VirtualSocketServer(pss_.get())),
305 fss_(new talk_base::FirewallSocketServer(vss_.get())),
306 ss_scope_(fss_.get()),
wu@webrtc.org364f2042013-11-20 21:49:41 +0000307 stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
308 cricket::STUN_SERVER_PORT)),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000309 stun_server_(Thread::Current(), stun_socket_addr_),
310 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
311 allocator_(new cricket::BasicPortAllocator(
312 &network_manager_, stun_socket_addr_,
313 SocketAddress(), SocketAddress(), SocketAddress())),
314 mediastream_signaling_(channel_manager_.get()),
315 ice_type_(PeerConnectionInterface::kAll) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000317 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000318 cricket::PORTALLOCATOR_DISABLE_RELAY |
319 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
320 EXPECT_TRUE(channel_manager_->Init());
321 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000322 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323 }
324
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000325 static void SetUpTestCase() {
326 talk_base::InitializeSSL();
327 }
328
329 static void TearDownTestCase() {
330 talk_base::CleanupSSL();
331 }
332
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000333 void AddInterface(const SocketAddress& addr) {
334 network_manager_.AddInterface(addr);
335 }
336
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000337 void SetIceTransportType(PeerConnectionInterface::IceTransportsType type) {
338 ice_type_ = type;
339 }
340
wu@webrtc.org91053e72013-08-10 07:18:04 +0000341 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000342 ASSERT_TRUE(session_.get() == NULL);
343 session_.reset(new WebRtcSessionForTest(
344 channel_manager_.get(), talk_base::Thread::Current(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000345 talk_base::Thread::Current(), allocator_.get(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 &observer_,
347 &mediastream_signaling_));
348
349 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
350 observer_.ice_connection_state_);
351 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
352 observer_.ice_gathering_state_);
353
wu@webrtc.org97077a32013-10-25 21:18:33 +0000354 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000355 identity_service, ice_type_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 }
357
358 void InitWithDtmfCodec() {
359 // Add kTelephoneEventCodec for dtmf test.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000360 const cricket::AudioCodec kTelephoneEventCodec(
361 106, "telephone-event", 8000, 0, 1, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 std::vector<cricket::AudioCodec> codecs;
363 codecs.push_back(kTelephoneEventCodec);
364 media_engine_->SetAudioCodecs(codecs);
365 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000366 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000367 }
368
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000369 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000370 FakeIdentityService* identity_service = new FakeIdentityService();
371 identity_service->set_should_fail(identity_request_should_fail);
372 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000373 }
374
375 // Creates a local offer and applies it. Starts ice.
376 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
377 // to decide which streams to create.
378 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000379 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380 SetLocalDescriptionWithoutError(offer);
381 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
382 observer_.ice_gathering_state_,
383 kIceCandidatesTimeout);
384 }
385
wu@webrtc.org91053e72013-08-10 07:18:04 +0000386 SessionDescriptionInterface* CreateOffer(
387 const webrtc::MediaConstraintsInterface* constraints) {
388 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
389 observer = new WebRtcSessionCreateSDPObserverForTest();
390 session_->CreateOffer(observer, constraints);
391 EXPECT_TRUE_WAIT(
392 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000393 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000394 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000395 }
396
397 SessionDescriptionInterface* CreateAnswer(
398 const webrtc::MediaConstraintsInterface* constraints) {
399 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
400 = new WebRtcSessionCreateSDPObserverForTest();
401 session_->CreateAnswer(observer, constraints);
402 EXPECT_TRUE_WAIT(
403 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000404 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000405 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000406 }
407
wu@webrtc.org364f2042013-11-20 21:49:41 +0000408 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409 return (session_->voice_channel() != NULL &&
410 session_->video_channel() != NULL);
411 }
412
wu@webrtc.org364f2042013-11-20 21:49:41 +0000413 void CheckTransportChannels() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000414 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
415 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
416 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
417 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
418 }
419
420 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
421 ASSERT_TRUE(session_.get() != NULL);
422 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
423 ASSERT_TRUE(content != NULL);
424 const cricket::AudioContentDescription* audio_content =
425 static_cast<const cricket::AudioContentDescription*>(
426 content->description);
427 ASSERT_TRUE(audio_content != NULL);
428 ASSERT_EQ(1U, audio_content->cryptos().size());
429 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
430 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
431 audio_content->cryptos()[0].cipher_suite);
432 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
433 audio_content->protocol());
434
435 content = cricket::GetFirstVideoContent(sdp);
436 ASSERT_TRUE(content != NULL);
437 const cricket::VideoContentDescription* video_content =
438 static_cast<const cricket::VideoContentDescription*>(
439 content->description);
440 ASSERT_TRUE(video_content != NULL);
441 ASSERT_EQ(1U, video_content->cryptos().size());
442 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
443 video_content->cryptos()[0].cipher_suite);
444 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
445 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
446 video_content->protocol());
447 }
448
449 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
450 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
451 ASSERT_TRUE(content != NULL);
452 const cricket::AudioContentDescription* audio_content =
453 static_cast<const cricket::AudioContentDescription*>(
454 content->description);
455 ASSERT_TRUE(audio_content != NULL);
456 ASSERT_EQ(0U, audio_content->cryptos().size());
457
458 content = cricket::GetFirstVideoContent(sdp);
459 ASSERT_TRUE(content != NULL);
460 const cricket::VideoContentDescription* video_content =
461 static_cast<const cricket::VideoContentDescription*>(
462 content->description);
463 ASSERT_TRUE(video_content != NULL);
464 ASSERT_EQ(0U, video_content->cryptos().size());
465
466 if (dtls) {
467 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
468 audio_content->protocol());
469 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
470 video_content->protocol());
471 } else {
472 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
473 audio_content->protocol());
474 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
475 video_content->protocol());
476 }
477 }
478
479 // Set the internal fake description factories to do DTLS-SRTP.
480 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000481 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000482 std::string identity_name = "WebRTC" +
483 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000484 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
485 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
487 }
488
489 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
490 bool expected) {
491 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
492 ASSERT_TRUE(audio != NULL);
493 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000494 const TransportInfo* video = sdp->GetTransportInfoByName("video");
495 ASSERT_TRUE(video != NULL);
496 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000497 }
498
499 void VerifyAnswerFromNonCryptoOffer() {
500 // Create a SDP without Crypto.
501 cricket::MediaSessionOptions options;
502 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000503 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000505 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000507 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
508 offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000509 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000510 // Answer should be NULL as no crypto params in offer.
511 ASSERT_TRUE(answer == NULL);
512 }
513
514 void VerifyAnswerFromCryptoOffer() {
515 cricket::MediaSessionOptions options;
516 options.has_video = true;
517 options.bundle_enabled = true;
518 scoped_ptr<JsepSessionDescription> offer(
519 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
520 ASSERT_TRUE(offer.get() != NULL);
521 VerifyCryptoParams(offer->description());
522 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000523 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 ASSERT_TRUE(answer.get() != NULL);
525 VerifyCryptoParams(answer->description());
526 }
527
528 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
529 const cricket::SessionDescription* desc2,
530 bool expect_equal) {
531 if (desc1->contents().size() != desc2->contents().size()) {
532 EXPECT_FALSE(expect_equal);
533 return;
534 }
535
536 const cricket::ContentInfos& contents = desc1->contents();
537 cricket::ContentInfos::const_iterator it = contents.begin();
538
539 for (; it != contents.end(); ++it) {
540 const cricket::TransportDescription* transport_desc1 =
541 desc1->GetTransportDescriptionByName(it->name);
542 const cricket::TransportDescription* transport_desc2 =
543 desc2->GetTransportDescriptionByName(it->name);
544 if (!transport_desc1 || !transport_desc2) {
545 EXPECT_FALSE(expect_equal);
546 return;
547 }
548 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
549 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
550 EXPECT_FALSE(expect_equal);
551 return;
552 }
553 }
554 EXPECT_TRUE(expect_equal);
555 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000556
557 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
558 std::string *sdp) {
559 const cricket::SessionDescription* desc = current_desc->description();
560 EXPECT_TRUE(current_desc->ToString(sdp));
561
562 const cricket::ContentInfos& contents = desc->contents();
563 cricket::ContentInfos::const_iterator it = contents.begin();
564 // Replace ufrag and pwd lines with empty strings.
565 for (; it != contents.end(); ++it) {
566 const cricket::TransportDescription* transport_desc =
567 desc->GetTransportDescriptionByName(it->name);
568 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
569 + "\r\n";
570 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
571 + "\r\n";
572 talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
573 "", 0,
574 sdp);
575 talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
576 "", 0,
577 sdp);
578 }
579 }
580
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000581 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
582 const std::string& modified_ice_ufrag,
583 const std::string& modified_ice_pwd,
584 std::string* sdp) {
585 const cricket::SessionDescription* desc = current_desc->description();
586 EXPECT_TRUE(current_desc->ToString(sdp));
587
588 const cricket::ContentInfos& contents = desc->contents();
589 cricket::ContentInfos::const_iterator it = contents.begin();
590 // Replace ufrag and pwd lines with |modified_ice_ufrag| and
591 // |modified_ice_pwd| strings.
592 for (; it != contents.end(); ++it) {
593 const cricket::TransportDescription* transport_desc =
594 desc->GetTransportDescriptionByName(it->name);
595 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
596 + "\r\n";
597 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
598 + "\r\n";
599 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n";
600 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n";
601 talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
602 mod_ufrag.c_str(), mod_ufrag.length(),
603 sdp);
604 talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
605 mod_pwd.c_str(), mod_pwd.length(),
606 sdp);
607 }
608 }
609
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 // Creates a remote offer and and applies it as a remote description,
611 // creates a local answer and applies is as a local description.
612 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
613 // to decide which local and remote streams to create.
614 void CreateAndSetRemoteOfferAndLocalAnswer() {
615 SessionDescriptionInterface* offer = CreateRemoteOffer();
616 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000617 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618 SetLocalDescriptionWithoutError(answer);
619 }
620 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
621 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
622 }
623 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
624 BaseSession::State expected_state) {
625 SetLocalDescriptionWithoutError(desc);
626 EXPECT_EQ(expected_state, session_->state());
627 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000628 void SetLocalDescriptionExpectError(const std::string& action,
629 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000630 SessionDescriptionInterface* desc) {
631 std::string error;
632 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000633 std::string sdp_type = "local ";
634 sdp_type.append(action);
635 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 EXPECT_NE(std::string::npos, error.find(expected_error));
637 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000638 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
639 SessionDescriptionInterface* desc) {
640 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
641 expected_error, desc);
642 }
643 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
644 SessionDescriptionInterface* desc) {
645 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
646 expected_error, desc);
647 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000648 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
649 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
650 }
651 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
652 BaseSession::State expected_state) {
653 SetRemoteDescriptionWithoutError(desc);
654 EXPECT_EQ(expected_state, session_->state());
655 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000656 void SetRemoteDescriptionExpectError(const std::string& action,
657 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 SessionDescriptionInterface* desc) {
659 std::string error;
660 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000661 std::string sdp_type = "remote ";
662 sdp_type.append(action);
663 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664 EXPECT_NE(std::string::npos, error.find(expected_error));
665 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000666 void SetRemoteDescriptionOfferExpectError(
667 const std::string& expected_error, SessionDescriptionInterface* desc) {
668 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
669 expected_error, desc);
670 }
671 void SetRemoteDescriptionPranswerExpectError(
672 const std::string& expected_error, SessionDescriptionInterface* desc) {
673 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
674 expected_error, desc);
675 }
676 void SetRemoteDescriptionAnswerExpectError(
677 const std::string& expected_error, SessionDescriptionInterface* desc) {
678 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
679 expected_error, desc);
680 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681
682 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
683 SessionDescriptionInterface** nocrypto_answer) {
684 // Create a SDP without Crypto.
685 cricket::MediaSessionOptions options;
686 options.has_video = true;
687 options.bundle_enabled = true;
688 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
689 ASSERT_TRUE(*offer != NULL);
690 VerifyCryptoParams((*offer)->description());
691
692 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
693 cricket::SEC_DISABLED);
694 EXPECT_TRUE(*nocrypto_answer != NULL);
695 }
696
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000697 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
698 SessionDescriptionInterface** nodtls_answer) {
699 cricket::MediaSessionOptions options;
700 options.has_video = true;
701 options.bundle_enabled = true;
702
703 talk_base::scoped_ptr<SessionDescriptionInterface> temp_offer(
704 CreateRemoteOffer(options, cricket::SEC_ENABLED));
705
706 *nodtls_answer =
707 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
708 EXPECT_TRUE(*nodtls_answer != NULL);
709 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
710 VerifyCryptoParams((*nodtls_answer)->description());
711
712 SetFactoryDtlsSrtp();
713 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
714 ASSERT_TRUE(*offer != NULL);
715 VerifyFingerprintStatus((*offer)->description(), true);
716 VerifyCryptoParams((*offer)->description());
717 }
718
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 JsepSessionDescription* CreateRemoteOfferWithVersion(
720 cricket::MediaSessionOptions options,
721 cricket::SecurePolicy secure_policy,
722 const std::string& session_version,
723 const SessionDescriptionInterface* current_desc) {
724 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
725 const cricket::SessionDescription* cricket_desc = NULL;
726 if (current_desc) {
727 cricket_desc = current_desc->description();
728 session_id = current_desc->session_id();
729 }
730
731 desc_factory_->set_secure(secure_policy);
732 JsepSessionDescription* offer(
733 new JsepSessionDescription(JsepSessionDescription::kOffer));
734 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
735 session_id, session_version)) {
736 delete offer;
737 offer = NULL;
738 }
739 return offer;
740 }
741 JsepSessionDescription* CreateRemoteOffer(
742 cricket::MediaSessionOptions options) {
743 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
744 kSessionVersion, NULL);
745 }
746 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000747 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
748 return CreateRemoteOfferWithVersion(
749 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000750 }
751 JsepSessionDescription* CreateRemoteOffer(
752 cricket::MediaSessionOptions options,
753 const SessionDescriptionInterface* current_desc) {
754 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
755 kSessionVersion, current_desc);
756 }
757
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000758 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
759 const char* sctp_stream_name, int new_port,
760 cricket::MediaSessionOptions options) {
761 options.data_channel_type = cricket::DCT_SCTP;
762 options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel",
763 sctp_stream_name);
764 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
765 }
766
767 // Takes ownership of offer_basis (and deletes it).
768 JsepSessionDescription* ChangeSDPSctpPort(
769 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
770 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
771 // SessionDescription from the mutated string.
772 const char* default_port_str = "5000";
773 char new_port_str[16];
774 talk_base::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
775 std::string offer_str;
776 offer_basis->ToString(&offer_str);
777 talk_base::replace_substrs(default_port_str, strlen(default_port_str),
778 new_port_str, strlen(new_port_str),
779 &offer_str);
780 JsepSessionDescription* offer = new JsepSessionDescription(
781 offer_basis->type());
782 delete offer_basis;
783 offer->Initialize(offer_str, NULL);
784 return offer;
785 }
786
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000787 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
788 // before this function to decide which streams to create.
789 JsepSessionDescription* CreateRemoteOffer() {
790 cricket::MediaSessionOptions options;
791 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
792 return CreateRemoteOffer(options, session_->remote_description());
793 }
794
795 JsepSessionDescription* CreateRemoteAnswer(
796 const SessionDescriptionInterface* offer,
797 cricket::MediaSessionOptions options,
798 cricket::SecurePolicy policy) {
799 desc_factory_->set_secure(policy);
800 const std::string session_id =
801 talk_base::ToString(talk_base::CreateRandomId64());
802 JsepSessionDescription* answer(
803 new JsepSessionDescription(JsepSessionDescription::kAnswer));
804 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
805 options, NULL),
806 session_id, kSessionVersion)) {
807 delete answer;
808 answer = NULL;
809 }
810 return answer;
811 }
812
813 JsepSessionDescription* CreateRemoteAnswer(
814 const SessionDescriptionInterface* offer,
815 cricket::MediaSessionOptions options) {
816 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
817 }
818
819 // Creates an answer session description with streams based on
820 // |mediastream_signaling_|. Call
821 // mediastream_signaling_.UseOptionsWithStreamX() before this function
822 // to decide which streams to create.
823 JsepSessionDescription* CreateRemoteAnswer(
824 const SessionDescriptionInterface* offer) {
825 cricket::MediaSessionOptions options;
826 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
827 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
828 }
829
830 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000831 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000832 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000833 mediastream_signaling_.SendAudioVideoStream1();
834 FakeConstraints constraints;
835 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000836 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000837 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
838 // and answer.
839 SetLocalDescriptionWithoutError(offer);
840
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000841 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
842 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000843 std::string sdp;
844 EXPECT_TRUE(answer->ToString(&sdp));
845
846 size_t expected_candidate_num = 2;
847 if (!rtcp_mux) {
848 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
849 // for rtp and rtcp.
850 expected_candidate_num = 4;
851 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000852 const std::string kRtcpMux = "a=rtcp-mux";
853 const std::string kXRtcpMux = "a=xrtcp-mux";
854 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
855 kXRtcpMux.c_str(), kXRtcpMux.length(),
856 &sdp);
857 }
858
859 SessionDescriptionInterface* new_answer = CreateSessionDescription(
860 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861
862 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000863 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
865 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
866 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
867 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
868 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
869 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
870 if (bundle) {
871 EXPECT_TRUE(c0.IsEquivalent(c1));
872 } else {
873 EXPECT_FALSE(c0.IsEquivalent(c1));
874 }
875 }
876 }
877 // Tests that we can only send DTMF when the dtmf codec is supported.
878 void TestCanInsertDtmf(bool can) {
879 if (can) {
880 InitWithDtmfCodec();
881 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000882 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000883 }
884 mediastream_signaling_.SendAudioVideoStream1();
885 CreateAndSetRemoteOfferAndLocalAnswer();
886 EXPECT_FALSE(session_->CanInsertDtmf(""));
887 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
888 }
889
890 // The method sets up a call from the session to itself, in a loopback
891 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000892 // disconnection, and then a permanent disconnection.
893 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 // by multiple tests with different allocators (e.g. with and without BUNDLE).
895 // While running the call, this method also checks if the session goes through
896 // the correct sequence of ICE states when a connection is established,
897 // broken, and re-established.
898 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000899 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
900 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901 // The Gathering state should go: New -> Gathering -> Completed.
902 void TestLoopbackCall() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000903 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000904 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000906 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907
908 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
909 observer_.ice_gathering_state_);
910 SetLocalDescriptionWithoutError(offer);
911 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
912 observer_.ice_connection_state_);
913 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
914 observer_.ice_gathering_state_,
915 kIceCandidatesTimeout);
916 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
917 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
918 observer_.ice_gathering_state_,
919 kIceCandidatesTimeout);
920
921 std::string sdp;
922 offer->ToString(&sdp);
923 SessionDescriptionInterface* desc =
924 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
925 ASSERT_TRUE(desc != NULL);
926 SetRemoteDescriptionWithoutError(desc);
927
928 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
929 observer_.ice_connection_state_,
930 kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +0000931
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000932 // The ice connection state is "Connected" too briefly to catch in a test.
933 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 observer_.ice_connection_state_,
935 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000936
937 // Adding firewall rule to block ping requests, which should cause
938 // transport channel failure.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000939 fss_->AddRule(false,
940 talk_base::FP_ANY,
941 talk_base::FD_ANY,
942 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
944 observer_.ice_connection_state_,
945 kIceCandidatesTimeout);
946
947 // Clearing the rules, session should move back to completed state.
948 fss_->ClearRules();
949 // Session is automatically calling OnSignalingReady after creation of
950 // new portallocator session which will allocate new set of candidates.
951
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000952 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953 observer_.ice_connection_state_,
954 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000955
956 // Now we block ping requests and wait until the ICE connection transitions
957 // to the Failed state. This will take at least 30 seconds because it must
958 // wait for the Port to timeout.
959 int port_timeout = 30000;
960 fss_->AddRule(false,
961 talk_base::FP_ANY,
962 talk_base::FD_ANY,
963 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
964 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed,
965 observer_.ice_connection_state_,
966 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967 }
968
969 void VerifyTransportType(const std::string& content_name,
970 cricket::TransportProtocol protocol) {
971 const cricket::Transport* transport = session_->GetTransport(content_name);
972 ASSERT_TRUE(transport != NULL);
973 EXPECT_EQ(protocol, transport->protocol());
974 }
975
976 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
977 void AddCNCodecs() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000978 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
979 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
980
981 // Add kCNCodec for dtmf test.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
983 codecs.push_back(kCNCodec1);
984 codecs.push_back(kCNCodec2);
985 media_engine_->SetAudioCodecs(codecs);
986 desc_factory_->set_audio_codecs(codecs);
987 }
988
989 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
990 const cricket::ContentDescription* description = content->description;
991 ASSERT(description != NULL);
992 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000993 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 ASSERT(audio_content_desc != NULL);
995 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
996 if (audio_content_desc->codecs()[i].name == "CN")
997 return false;
998 }
999 return true;
1000 }
1001
1002 void SetLocalDescriptionWithDataChannel() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001003 webrtc::InternalDataChannelInit dci;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001004 dci.reliable = false;
1005 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001006 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001007 SetLocalDescriptionWithoutError(offer);
1008 }
1009
wu@webrtc.org91053e72013-08-10 07:18:04 +00001010 void VerifyMultipleAsyncCreateDescription(
1011 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +00001012 InitWithDtls(!success);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001013 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001014 if (type == CreateSessionDescriptionRequest::kAnswer) {
1015 cricket::MediaSessionOptions options;
1016 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001017 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001018 ASSERT_TRUE(offer.get() != NULL);
1019 SetRemoteDescriptionWithoutError(offer.release());
1020 }
1021
1022 const int kNumber = 3;
1023 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
1024 observers[kNumber];
1025 for (int i = 0; i < kNumber; ++i) {
1026 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
1027 if (type == CreateSessionDescriptionRequest::kOffer) {
1028 session_->CreateOffer(observers[i], NULL);
1029 } else {
1030 session_->CreateAnswer(observers[i], NULL);
1031 }
1032 }
1033
1034 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1035 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1036 WebRtcSessionCreateSDPObserverForTest::kFailed;
1037
1038 for (int i = 0; i < kNumber; ++i) {
1039 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1040 if (success) {
1041 EXPECT_TRUE(observers[i]->description() != NULL);
1042 } else {
1043 EXPECT_TRUE(observers[i]->description() == NULL);
1044 }
1045 }
1046 }
1047
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001048 cricket::FakeMediaEngine* media_engine_;
1049 cricket::FakeDataEngine* data_engine_;
1050 cricket::FakeDeviceManager* device_manager_;
1051 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
1052 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001053 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001054 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1055 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
1056 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
1057 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
1058 talk_base::SocketServerScope ss_scope_;
wu@webrtc.org364f2042013-11-20 21:49:41 +00001059 talk_base::SocketAddress stun_socket_addr_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 cricket::TestStunServer stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001061 cricket::TestTurnServer turn_server_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001062 talk_base::FakeNetworkManager network_manager_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001063 talk_base::scoped_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001064 PeerConnectionFactoryInterface::Options options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001065 talk_base::scoped_ptr<FakeConstraints> constraints_;
1066 FakeMediaStreamSignaling mediastream_signaling_;
1067 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
1068 MockIceObserver observer_;
1069 cricket::FakeVideoMediaChannel* video_channel_;
1070 cricket::FakeVoiceMediaChannel* voice_channel_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001071 PeerConnectionInterface::IceTransportsType ice_type_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001072};
1073
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
1075 InitWithDtls();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001076 // SDES is disabled when DTLS is on.
1077 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001078}
1079
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001080TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001081 Init(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001082 // SDES is required if DTLS is off.
1083 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001084}
1085
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001086TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1087 TestSessionCandidatesWithBundleRtcpMux(false, false);
1088}
1089
1090// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1091// with rtcp-mux and/or bundle.
1092TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1093 TestSessionCandidatesWithBundleRtcpMux(false, true);
1094}
1095
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001096TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1097 TestSessionCandidatesWithBundleRtcpMux(true, true);
1098}
1099
1100TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001101 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1102 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001103 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104 mediastream_signaling_.SendAudioVideoStream1();
1105 InitiateCall();
1106 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1107 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1108 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1109}
1110
1111TEST_F(WebRtcSessionTest, TestStunError) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001112 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1113 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
1114 fss_->AddRule(false,
1115 talk_base::FP_UDP,
1116 talk_base::FD_ANY,
1117 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001118 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001119 mediastream_signaling_.SendAudioVideoStream1();
1120 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001121 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001122 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1123 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1124 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1125}
1126
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001127TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
1128 Init(NULL);
1129 SessionDescriptionInterface* offer = NULL;
1130 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1131 std::string unknown_action;
1132 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1133 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1134}
1135
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001136// Test creating offers and receive answers and make sure the
1137// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001138TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001139 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001141 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001142 const std::string session_id_orig = offer->session_id();
1143 const std::string session_version_orig = offer->session_version();
1144 SetLocalDescriptionWithoutError(offer);
1145
1146 mediastream_signaling_.SendAudioVideoStream2();
1147 SessionDescriptionInterface* answer =
1148 CreateRemoteAnswer(session_->local_description());
1149 SetRemoteDescriptionWithoutError(answer);
1150
1151 video_channel_ = media_engine_->GetVideoChannel(0);
1152 voice_channel_ = media_engine_->GetVoiceChannel(0);
1153
1154 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1155 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1156
1157 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1158 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1159
1160 ASSERT_EQ(1u, video_channel_->send_streams().size());
1161 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1162 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1163 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1164
1165 // Create new offer without send streams.
1166 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001167 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001168
1169 // Verify the session id is the same and the session version is
1170 // increased.
1171 EXPECT_EQ(session_id_orig, offer->session_id());
1172 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1173 talk_base::FromString<uint64>(offer->session_version()));
1174
1175 SetLocalDescriptionWithoutError(offer);
1176
1177 mediastream_signaling_.SendAudioVideoStream2();
1178 answer = CreateRemoteAnswer(session_->local_description());
1179 SetRemoteDescriptionWithoutError(answer);
1180
1181 EXPECT_EQ(0u, video_channel_->send_streams().size());
1182 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1183
1184 // Make sure the receive streams have not changed.
1185 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1186 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1187 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1188 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1189}
1190
1191// Test receiving offers and creating answers and make sure the
1192// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001193TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001194 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001196 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001197 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198 SetRemoteDescriptionWithoutError(offer);
1199
1200 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001201 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001202 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001203 SetLocalDescriptionWithoutError(answer);
1204
1205 const std::string session_id_orig = answer->session_id();
1206 const std::string session_version_orig = answer->session_version();
1207
1208 video_channel_ = media_engine_->GetVideoChannel(0);
1209 voice_channel_ = media_engine_->GetVoiceChannel(0);
1210
1211 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1212 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1213
1214 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1215 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1216
1217 ASSERT_EQ(1u, video_channel_->send_streams().size());
1218 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1219 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1220 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1221
1222 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001223 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001224 SetRemoteDescriptionWithoutError(offer);
1225
1226 // Answer by turning off all send streams.
1227 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001228 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229
1230 // Verify the session id is the same and the session version is
1231 // increased.
1232 EXPECT_EQ(session_id_orig, answer->session_id());
1233 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1234 talk_base::FromString<uint64>(answer->session_version()));
1235 SetLocalDescriptionWithoutError(answer);
1236
1237 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1238 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1239 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1240 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1241 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1242 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1243
1244 // Make sure we have no send streams.
1245 EXPECT_EQ(0u, video_channel_->send_streams().size());
1246 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1247}
1248
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001249TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
1250 Init(NULL);
1251 media_engine_->set_fail_create_channel(true);
1252
1253 SessionDescriptionInterface* offer = CreateOffer(NULL);
1254 ASSERT_TRUE(offer != NULL);
1255 // SetRemoteDescription and SetLocalDescription will take the ownership of
1256 // the offer.
1257 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
1258 offer = CreateOffer(NULL);
1259 ASSERT_TRUE(offer != NULL);
1260 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1261}
1262
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001263//
1264// Tests for creating/setting SDP under different SDES/DTLS polices:
1265//
1266// --DTLS off and SDES on
1267// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1268// set local/remote offer/answer with crypto --> success
1269// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1270// failure
1271// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1272// failure
1273// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1274// failure
1275//
1276// --DTLS on and SDES off
1277// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1278// set local/remote offer/answer with DTLS fingerprint --> success
1279// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1280// fingerprint --> failure
1281// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1282// --> failure
1283// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1284// --> failure
1285//
1286// --Encryption disabled: DTLS off and SDES off
1287// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1288// answer without SDES or DTLS --> success
1289// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1290// answer without SDES or DTLS --> success
1291//
1292
1293// Test that we return a failure when applying a remote/local offer that doesn't
1294// have cryptos enabled when DTLS is off.
1295TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001296 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001297 cricket::MediaSessionOptions options;
1298 options.has_video = true;
1299 JsepSessionDescription* offer = CreateRemoteOffer(
1300 options, cricket::SEC_DISABLED);
1301 ASSERT_TRUE(offer != NULL);
1302 VerifyNoCryptoParams(offer->description(), false);
1303 // SetRemoteDescription and SetLocalDescription will take the ownership of
1304 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001305 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1307 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001308 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309}
1310
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001311// Test that we return a failure when applying a local answer that doesn't have
1312// cryptos enabled when DTLS is off.
1313TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001314 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001315 SessionDescriptionInterface* offer = NULL;
1316 SessionDescriptionInterface* answer = NULL;
1317 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1318 // SetRemoteDescription and SetLocalDescription will take the ownership of
1319 // the offer.
1320 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001321 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322}
1323
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001324// Test we will return fail when apply an remote answer that doesn't have
1325// crypto enabled when DTLS is off.
1326TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001327 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001328 SessionDescriptionInterface* offer = NULL;
1329 SessionDescriptionInterface* answer = NULL;
1330 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1331 // SetRemoteDescription and SetLocalDescription will take the ownership of
1332 // the offer.
1333 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001334 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335}
1336
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001337// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1338// and that we return an answer with a DTLS fingerprint.
1339TEST_F(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342 InitWithDtls();
1343 SetFactoryDtlsSrtp();
1344 cricket::MediaSessionOptions options;
1345 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001346 JsepSessionDescription* offer =
1347 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348 ASSERT_TRUE(offer != NULL);
1349 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001350 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001351
1352 // SetRemoteDescription will take the ownership of the offer.
1353 SetRemoteDescriptionWithoutError(offer);
1354
1355 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001356 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001357 ASSERT_TRUE(answer != NULL);
1358 VerifyFingerprintStatus(answer->description(), true);
1359 // Check that we don't have an a=crypto line in the answer.
1360 VerifyNoCryptoParams(answer->description(), true);
1361
1362 // Now set the local description, which should work, even without a=crypto.
1363 SetLocalDescriptionWithoutError(answer);
1364}
1365
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001366// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1367// and then we accept a remote answer with a DTLS fingerprint successfully.
1368TEST_F(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
1369 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1370 mediastream_signaling_.SendAudioVideoStream1();
1371 InitWithDtls();
1372 SetFactoryDtlsSrtp();
1373
1374 // Verify that we get a crypto fingerprint in the answer.
1375 SessionDescriptionInterface* offer = CreateOffer(NULL);
1376 ASSERT_TRUE(offer != NULL);
1377 VerifyFingerprintStatus(offer->description(), true);
1378 // Check that we don't have an a=crypto line in the offer.
1379 VerifyNoCryptoParams(offer->description(), true);
1380
1381 // Now set the local description, which should work, even without a=crypto.
1382 SetLocalDescriptionWithoutError(offer);
1383
1384 cricket::MediaSessionOptions options;
1385 options.has_video = true;
1386 JsepSessionDescription* answer =
1387 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1388 ASSERT_TRUE(answer != NULL);
1389 VerifyFingerprintStatus(answer->description(), true);
1390 VerifyNoCryptoParams(answer->description(), true);
1391
1392 // SetRemoteDescription will take the ownership of the answer.
1393 SetRemoteDescriptionWithoutError(answer);
1394}
1395
1396// Test that if we support DTLS and the other side didn't offer a fingerprint,
1397// we will fail to set the remote description.
1398TEST_F(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001399 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1400 InitWithDtls();
1401 cricket::MediaSessionOptions options;
1402 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001403 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001404 JsepSessionDescription* offer = CreateRemoteOffer(
1405 options, cricket::SEC_REQUIRED);
1406 ASSERT_TRUE(offer != NULL);
1407 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001408 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001409
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001410 // SetRemoteDescription will take the ownership of the offer.
1411 SetRemoteDescriptionOfferExpectError(
1412 kSdpWithoutDtlsFingerprint, offer);
1413
1414 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1415 // SetLocalDescription will take the ownership of the offer.
1416 SetLocalDescriptionOfferExpectError(
1417 kSdpWithoutDtlsFingerprint, offer);
1418}
1419
1420// Test that we return a failure when applying a local answer that doesn't have
1421// a DTLS fingerprint when DTLS is required.
1422TEST_F(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
1423 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1424 InitWithDtls();
1425 SessionDescriptionInterface* offer = NULL;
1426 SessionDescriptionInterface* answer = NULL;
1427 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1428
1429 // SetRemoteDescription and SetLocalDescription will take the ownership of
1430 // the offer and answer.
1431 SetRemoteDescriptionWithoutError(offer);
1432 SetLocalDescriptionAnswerExpectError(
1433 kSdpWithoutDtlsFingerprint, answer);
1434}
1435
1436// Test that we return a failure when applying a remote answer that doesn't have
1437// a DTLS fingerprint when DTLS is required.
1438TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
1439 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1440 InitWithDtls();
1441 SessionDescriptionInterface* offer = CreateOffer(NULL);
1442 cricket::MediaSessionOptions options;
1443 options.has_video = true;
1444 JsepSessionDescription* answer =
1445 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
1446
1447 // SetRemoteDescription and SetLocalDescription will take the ownership of
1448 // the offer and answer.
1449 SetLocalDescriptionWithoutError(offer);
1450 SetRemoteDescriptionAnswerExpectError(
1451 kSdpWithoutDtlsFingerprint, answer);
1452}
1453
1454// Test that we create a local offer without SDES or DTLS and accept a remote
1455// answer without SDES or DTLS when encryption is disabled.
1456TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
1457 mediastream_signaling_.SendAudioVideoStream1();
1458 options_.disable_encryption = true;
1459 InitWithDtls();
1460
1461 // Verify that we get a crypto fingerprint in the answer.
1462 SessionDescriptionInterface* offer = CreateOffer(NULL);
1463 ASSERT_TRUE(offer != NULL);
1464 VerifyFingerprintStatus(offer->description(), false);
1465 // Check that we don't have an a=crypto line in the offer.
1466 VerifyNoCryptoParams(offer->description(), false);
1467
1468 // Now set the local description, which should work, even without a=crypto.
1469 SetLocalDescriptionWithoutError(offer);
1470
1471 cricket::MediaSessionOptions options;
1472 options.has_video = true;
1473 JsepSessionDescription* answer =
1474 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1475 ASSERT_TRUE(answer != NULL);
1476 VerifyFingerprintStatus(answer->description(), false);
1477 VerifyNoCryptoParams(answer->description(), false);
1478
1479 // SetRemoteDescription will take the ownership of the answer.
1480 SetRemoteDescriptionWithoutError(answer);
1481}
1482
1483// Test that we create a local answer without SDES or DTLS and accept a remote
1484// offer without SDES or DTLS when encryption is disabled.
1485TEST_F(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
1486 options_.disable_encryption = true;
1487 InitWithDtls();
1488
1489 cricket::MediaSessionOptions options;
1490 options.has_video = true;
1491 JsepSessionDescription* offer =
1492 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1493 ASSERT_TRUE(offer != NULL);
1494 VerifyFingerprintStatus(offer->description(), false);
1495 VerifyNoCryptoParams(offer->description(), false);
1496
1497 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 SetRemoteDescriptionWithoutError(offer);
1499
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001500 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001501 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502 ASSERT_TRUE(answer != NULL);
1503 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001504 // Check that we don't have an a=crypto line in the answer.
1505 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001507 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508 SetLocalDescriptionWithoutError(answer);
1509}
1510
1511TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001512 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 mediastream_signaling_.SendNothing();
1514 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001515 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001516 SetLocalDescriptionWithoutError(offer);
1517
1518 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001519 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 SetLocalDescriptionWithoutError(offer2);
1521}
1522
1523TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001524 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 mediastream_signaling_.SendNothing();
1526 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001527 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 SetRemoteDescriptionWithoutError(offer);
1529
wu@webrtc.org91053e72013-08-10 07:18:04 +00001530 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 SetRemoteDescriptionWithoutError(offer2);
1532}
1533
1534TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001535 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001537 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001538 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001539 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001540 SetRemoteDescriptionOfferExpectError(
1541 "Called in wrong state: STATE_SENTINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001542}
1543
1544TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001545 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001547 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001548 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001549 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001550 SetLocalDescriptionOfferExpectError(
1551 "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552}
1553
1554TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001555 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556 mediastream_signaling_.SendNothing();
1557 SessionDescriptionInterface* offer = CreateRemoteOffer();
1558 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1559
1560 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001561 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001562 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1563 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1564
1565 mediastream_signaling_.SendAudioVideoStream1();
1566 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001567 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001568 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1569
1570 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1571
1572 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001573 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1575}
1576
1577TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001578 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001580 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1582
1583 JsepSessionDescription* pranswer =
1584 CreateRemoteAnswer(session_->local_description());
1585 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1586
1587 SetRemoteDescriptionExpectState(pranswer,
1588 BaseSession::STATE_RECEIVEDPRACCEPT);
1589
1590 mediastream_signaling_.SendAudioVideoStream1();
1591 JsepSessionDescription* pranswer2 =
1592 CreateRemoteAnswer(session_->local_description());
1593 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1594
1595 SetRemoteDescriptionExpectState(pranswer2,
1596 BaseSession::STATE_RECEIVEDPRACCEPT);
1597
1598 mediastream_signaling_.SendAudioVideoStream2();
1599 SessionDescriptionInterface* answer =
1600 CreateRemoteAnswer(session_->local_description());
1601 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1602}
1603
1604TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001605 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606 mediastream_signaling_.SendNothing();
1607 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001608 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001609 SessionDescriptionInterface* answer =
1610 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001611 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1612 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613}
1614
1615TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001616 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 mediastream_signaling_.SendNothing();
1618 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001619 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 SessionDescriptionInterface* answer =
1621 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001622 SetRemoteDescriptionAnswerExpectError(
1623 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624}
1625
1626TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001627 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628 mediastream_signaling_.SendAudioVideoStream1();
1629
1630 cricket::Candidate candidate;
1631 candidate.set_component(1);
1632 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1633
1634 // Fail since we have not set a offer description.
1635 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1636
wu@webrtc.org91053e72013-08-10 07:18:04 +00001637 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638 SetLocalDescriptionWithoutError(offer);
1639 // Candidate should be allowed to add before remote description.
1640 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1641 candidate.set_component(2);
1642 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1643 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1644
1645 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1646 session_->local_description());
1647 SetRemoteDescriptionWithoutError(answer);
1648
1649 // Verifying the candidates are copied properly from internal vector.
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(2u, candidates->count());
1657 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1658 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1659 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1660 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1661
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001662 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
1663 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 candidate.set_component(2);
1665 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1666 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001667 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668
1669 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1670 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1671}
1672
1673// Test that a remote candidate is added to the remote session description and
1674// that it is retained if the remote session description is changed.
1675TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001676 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677 cricket::Candidate candidate1;
1678 candidate1.set_component(1);
1679 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1680 candidate1);
1681 mediastream_signaling_.SendAudioVideoStream1();
1682 CreateAndSetRemoteOfferAndLocalAnswer();
1683
1684 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1685 const SessionDescriptionInterface* remote_desc =
1686 session_->remote_description();
1687 ASSERT_TRUE(remote_desc != NULL);
1688 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1689 const IceCandidateCollection* candidates =
1690 remote_desc->candidates(kMediaContentIndex0);
1691 ASSERT_EQ(1u, candidates->count());
1692 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1693
1694 // Update the RemoteSessionDescription with a new session description and
1695 // a candidate and check that the new remote session description contains both
1696 // candidates.
1697 SessionDescriptionInterface* offer = CreateRemoteOffer();
1698 cricket::Candidate candidate2;
1699 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1700 candidate2);
1701 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1702 SetRemoteDescriptionWithoutError(offer);
1703
1704 remote_desc = session_->remote_description();
1705 ASSERT_TRUE(remote_desc != NULL);
1706 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1707 candidates = remote_desc->candidates(kMediaContentIndex0);
1708 ASSERT_EQ(2u, candidates->count());
1709 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1710 // Username and password have be updated with the TransportInfo of the
1711 // SessionDescription, won't be equal to the original one.
1712 candidate2.set_username(candidates->at(0)->candidate().username());
1713 candidate2.set_password(candidates->at(0)->candidate().password());
1714 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1715 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1716 // No need to verify the username and password.
1717 candidate1.set_username(candidates->at(1)->candidate().username());
1718 candidate1.set_password(candidates->at(1)->candidate().password());
1719 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1720
1721 // Test that the candidate is ignored if we can add the same candidate again.
1722 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1723}
1724
1725// Test that local candidates are added to the local session description and
1726// that they are retained if the local session description is changed.
1727TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001728 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001729 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730 mediastream_signaling_.SendAudioVideoStream1();
1731 CreateAndSetRemoteOfferAndLocalAnswer();
1732
1733 const SessionDescriptionInterface* local_desc = session_->local_description();
1734 const IceCandidateCollection* candidates =
1735 local_desc->candidates(kMediaContentIndex0);
1736 ASSERT_TRUE(candidates != NULL);
1737 EXPECT_EQ(0u, candidates->count());
1738
1739 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1740
1741 local_desc = session_->local_description();
1742 candidates = local_desc->candidates(kMediaContentIndex0);
1743 ASSERT_TRUE(candidates != NULL);
1744 EXPECT_LT(0u, candidates->count());
1745 candidates = local_desc->candidates(1);
1746 ASSERT_TRUE(candidates != NULL);
1747 EXPECT_LT(0u, candidates->count());
1748
1749 // Update the session descriptions.
1750 mediastream_signaling_.SendAudioVideoStream1();
1751 CreateAndSetRemoteOfferAndLocalAnswer();
1752
1753 local_desc = session_->local_description();
1754 candidates = local_desc->candidates(kMediaContentIndex0);
1755 ASSERT_TRUE(candidates != NULL);
1756 EXPECT_LT(0u, candidates->count());
1757 candidates = local_desc->candidates(1);
1758 ASSERT_TRUE(candidates != NULL);
1759 EXPECT_LT(0u, candidates->count());
1760}
1761
1762// Test that we can set a remote session description with remote candidates.
1763TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001764 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001765
1766 cricket::Candidate candidate1;
1767 candidate1.set_component(1);
1768 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1769 candidate1);
1770 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001771 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001772
1773 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1774 SetRemoteDescriptionWithoutError(offer);
1775
1776 const SessionDescriptionInterface* remote_desc =
1777 session_->remote_description();
1778 ASSERT_TRUE(remote_desc != NULL);
1779 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1780 const IceCandidateCollection* candidates =
1781 remote_desc->candidates(kMediaContentIndex0);
1782 ASSERT_EQ(1u, candidates->count());
1783 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1784
wu@webrtc.org91053e72013-08-10 07:18:04 +00001785 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001786 SetLocalDescriptionWithoutError(answer);
1787}
1788
1789// Test that offers and answers contains ice candidates when Ice candidates have
1790// been gathered.
1791TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001792 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001793 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001794 mediastream_signaling_.SendAudioVideoStream1();
1795 // Ice is started but candidates are not provided until SetLocalDescription
1796 // is called.
1797 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1798 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1799 CreateAndSetRemoteOfferAndLocalAnswer();
1800 // Wait until at least one local candidate has been collected.
1801 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1802 kIceCandidatesTimeout);
1803 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1804 kIceCandidatesTimeout);
1805
1806 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001807 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001808 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1809 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1810 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1811 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1812
1813 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1814 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001815 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1817 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1818 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1819 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1820 SetLocalDescriptionWithoutError(answer);
1821}
1822
1823// Verifies TransportProxy and media channels are created with content names
1824// present in the SessionDescription.
1825TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001826 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001827 mediastream_signaling_.SendAudioVideoStream1();
1828 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001829 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001830
1831 // CreateOffer creates session description with the content names "audio" and
1832 // "video". Goal is to modify these content names and verify transport channel
1833 // proxy in the BaseSession, as proxies are created with the content names
1834 // present in SDP.
1835 std::string sdp;
1836 EXPECT_TRUE(offer->ToString(&sdp));
1837 const std::string kAudioMid = "a=mid:audio";
1838 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1839 const std::string kVideoMid = "a=mid:video";
1840 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1841
1842 // Replacing |audio| with |audio_content_name|.
1843 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1844 kAudioMidReplaceStr.c_str(),
1845 kAudioMidReplaceStr.length(),
1846 &sdp);
1847 // Replacing |video| with |video_content_name|.
1848 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1849 kVideoMidReplaceStr.c_str(),
1850 kVideoMidReplaceStr.length(),
1851 &sdp);
1852
1853 SessionDescriptionInterface* modified_offer =
1854 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1855
1856 SetRemoteDescriptionWithoutError(modified_offer);
1857
1858 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001859 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001860 SetLocalDescriptionWithoutError(answer);
1861
1862 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1863 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1864 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1865 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1866}
1867
1868// Test that an offer contains the correct media content descriptions based on
1869// the send streams when no constraints have been set.
1870TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001871 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001873 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001874 ASSERT_TRUE(offer != NULL);
1875 const cricket::ContentInfo* content =
1876 cricket::GetFirstAudioContent(offer->description());
1877 EXPECT_TRUE(content != NULL);
1878 content = cricket::GetFirstVideoContent(offer->description());
1879 EXPECT_TRUE(content == NULL);
1880}
1881
1882// Test that an offer contains the correct media content descriptions based on
1883// the send streams when no constraints have been set.
1884TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001885 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001886 // Test Audio only offer.
1887 mediastream_signaling_.UseOptionsAudioOnly();
1888 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001889 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 const cricket::ContentInfo* content =
1891 cricket::GetFirstAudioContent(offer->description());
1892 EXPECT_TRUE(content != NULL);
1893 content = cricket::GetFirstVideoContent(offer->description());
1894 EXPECT_TRUE(content == NULL);
1895
1896 // Test Audio / Video offer.
1897 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001898 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001899 content = cricket::GetFirstAudioContent(offer->description());
1900 EXPECT_TRUE(content != NULL);
1901 content = cricket::GetFirstVideoContent(offer->description());
1902 EXPECT_TRUE(content != NULL);
1903}
1904
1905// Test that an offer contains no media content descriptions if
1906// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1907TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001908 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 webrtc::FakeConstraints constraints_no_receive;
1910 constraints_no_receive.SetMandatoryReceiveAudio(false);
1911 constraints_no_receive.SetMandatoryReceiveVideo(false);
1912
1913 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001914 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915 ASSERT_TRUE(offer != NULL);
1916 const cricket::ContentInfo* content =
1917 cricket::GetFirstAudioContent(offer->description());
1918 EXPECT_TRUE(content == NULL);
1919 content = cricket::GetFirstVideoContent(offer->description());
1920 EXPECT_TRUE(content == NULL);
1921}
1922
1923// Test that an offer contains only audio media content descriptions if
1924// kOfferToReceiveAudio constraints are set to true.
1925TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001926 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001927 webrtc::FakeConstraints constraints_audio_only;
1928 constraints_audio_only.SetMandatoryReceiveAudio(true);
1929 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001930 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931
1932 const cricket::ContentInfo* content =
1933 cricket::GetFirstAudioContent(offer->description());
1934 EXPECT_TRUE(content != NULL);
1935 content = cricket::GetFirstVideoContent(offer->description());
1936 EXPECT_TRUE(content == NULL);
1937}
1938
1939// Test that an offer contains audio and video media content descriptions if
1940// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1941TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001942 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001943 // Test Audio / Video offer.
1944 webrtc::FakeConstraints constraints_audio_video;
1945 constraints_audio_video.SetMandatoryReceiveAudio(true);
1946 constraints_audio_video.SetMandatoryReceiveVideo(true);
1947 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001948 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001949 const cricket::ContentInfo* content =
1950 cricket::GetFirstAudioContent(offer->description());
1951
1952 EXPECT_TRUE(content != NULL);
1953 content = cricket::GetFirstVideoContent(offer->description());
1954 EXPECT_TRUE(content != NULL);
1955
1956 // TODO(perkj): Should the direction be set to SEND_ONLY if
1957 // The constraints is set to not receive audio or video but a track is added?
1958}
1959
1960// Test that an answer can not be created if the last remote description is not
1961// an offer.
1962TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001963 Init(NULL);
1964 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001965 SetLocalDescriptionWithoutError(offer);
1966 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1967 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001968 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001969}
1970
1971// Test that an answer contains the correct media content descriptions when no
1972// constraints have been set.
1973TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001974 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975 // Create a remote offer with audio and video content.
1976 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1977 SetRemoteDescriptionWithoutError(offer.release());
1978 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001979 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 const cricket::ContentInfo* content =
1981 cricket::GetFirstAudioContent(answer->description());
1982 ASSERT_TRUE(content != NULL);
1983 EXPECT_FALSE(content->rejected);
1984
1985 content = cricket::GetFirstVideoContent(answer->description());
1986 ASSERT_TRUE(content != NULL);
1987 EXPECT_FALSE(content->rejected);
1988}
1989
1990// Test that an answer contains the correct media content descriptions when no
1991// constraints have been set and the offer only contain audio.
1992TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001993 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994 // Create a remote offer with audio only.
1995 cricket::MediaSessionOptions options;
1996 options.has_audio = true;
1997 options.has_video = false;
1998 talk_base::scoped_ptr<JsepSessionDescription> offer(
1999 CreateRemoteOffer(options));
2000 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
2001 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
2002
2003 SetRemoteDescriptionWithoutError(offer.release());
2004 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002005 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002006 const cricket::ContentInfo* content =
2007 cricket::GetFirstAudioContent(answer->description());
2008 ASSERT_TRUE(content != NULL);
2009 EXPECT_FALSE(content->rejected);
2010
2011 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
2012}
2013
2014// Test that an answer contains the correct media content descriptions when no
2015// constraints have been set.
2016TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002017 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018 // Create a remote offer with audio and video content.
2019 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2020 SetRemoteDescriptionWithoutError(offer.release());
2021 // Test with a stream with tracks.
2022 mediastream_signaling_.SendAudioVideoStream1();
2023 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002024 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025 const cricket::ContentInfo* content =
2026 cricket::GetFirstAudioContent(answer->description());
2027 ASSERT_TRUE(content != NULL);
2028 EXPECT_FALSE(content->rejected);
2029
2030 content = cricket::GetFirstVideoContent(answer->description());
2031 ASSERT_TRUE(content != NULL);
2032 EXPECT_FALSE(content->rejected);
2033}
2034
2035// Test that an answer contains the correct media content descriptions when
2036// constraints have been set but no stream is sent.
2037TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002038 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039 // Create a remote offer with audio and video content.
2040 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2041 SetRemoteDescriptionWithoutError(offer.release());
2042
2043 webrtc::FakeConstraints constraints_no_receive;
2044 constraints_no_receive.SetMandatoryReceiveAudio(false);
2045 constraints_no_receive.SetMandatoryReceiveVideo(false);
2046
2047 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002048 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049 const cricket::ContentInfo* content =
2050 cricket::GetFirstAudioContent(answer->description());
2051 ASSERT_TRUE(content != NULL);
2052 EXPECT_TRUE(content->rejected);
2053
2054 content = cricket::GetFirstVideoContent(answer->description());
2055 ASSERT_TRUE(content != NULL);
2056 EXPECT_TRUE(content->rejected);
2057}
2058
2059// Test that an answer contains the correct media content descriptions when
2060// constraints have been set and streams are sent.
2061TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002062 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002063 // Create a remote offer with audio and video content.
2064 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2065 SetRemoteDescriptionWithoutError(offer.release());
2066
2067 webrtc::FakeConstraints constraints_no_receive;
2068 constraints_no_receive.SetMandatoryReceiveAudio(false);
2069 constraints_no_receive.SetMandatoryReceiveVideo(false);
2070
2071 // Test with a stream with tracks.
2072 mediastream_signaling_.SendAudioVideoStream1();
2073 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002074 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075
2076 // TODO(perkj): Should the direction be set to SEND_ONLY?
2077 const cricket::ContentInfo* content =
2078 cricket::GetFirstAudioContent(answer->description());
2079 ASSERT_TRUE(content != NULL);
2080 EXPECT_FALSE(content->rejected);
2081
2082 // TODO(perkj): Should the direction be set to SEND_ONLY?
2083 content = cricket::GetFirstVideoContent(answer->description());
2084 ASSERT_TRUE(content != NULL);
2085 EXPECT_FALSE(content->rejected);
2086}
2087
2088TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2089 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002090 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002091 webrtc::FakeConstraints constraints;
2092 constraints.SetOptionalVAD(false);
2093 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002094 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002095 const cricket::ContentInfo* content =
2096 cricket::GetFirstAudioContent(offer->description());
2097 EXPECT_TRUE(content != NULL);
2098 EXPECT_TRUE(VerifyNoCNCodecs(content));
2099}
2100
2101TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2102 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002103 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002104 // Create a remote offer with audio and video content.
2105 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2106 SetRemoteDescriptionWithoutError(offer.release());
2107
2108 webrtc::FakeConstraints constraints;
2109 constraints.SetOptionalVAD(false);
2110 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002111 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002112 const cricket::ContentInfo* content =
2113 cricket::GetFirstAudioContent(answer->description());
2114 ASSERT_TRUE(content != NULL);
2115 EXPECT_TRUE(VerifyNoCNCodecs(content));
2116}
2117
2118// This test verifies the call setup when remote answer with audio only and
2119// later updates with video.
2120TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002121 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002122 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2123 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2124
2125 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002126 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127
2128 cricket::MediaSessionOptions options;
2129 options.has_video = false;
2130 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2131
2132 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2133 // and answer;
2134 SetLocalDescriptionWithoutError(offer);
2135 SetRemoteDescriptionWithoutError(answer);
2136
2137 video_channel_ = media_engine_->GetVideoChannel(0);
2138 voice_channel_ = media_engine_->GetVoiceChannel(0);
2139
2140 ASSERT_TRUE(video_channel_ == NULL);
2141
2142 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2143 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2144 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2145
2146 // Let the remote end update the session descriptions, with Audio and Video.
2147 mediastream_signaling_.SendAudioVideoStream2();
2148 CreateAndSetRemoteOfferAndLocalAnswer();
2149
2150 video_channel_ = media_engine_->GetVideoChannel(0);
2151 voice_channel_ = media_engine_->GetVoiceChannel(0);
2152
2153 ASSERT_TRUE(video_channel_ != NULL);
2154 ASSERT_TRUE(voice_channel_ != NULL);
2155
2156 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2157 ASSERT_EQ(1u, video_channel_->send_streams().size());
2158 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2159 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2160 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2161 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2162 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2163 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2164
2165 // Change session back to audio only.
2166 mediastream_signaling_.UseOptionsAudioOnly();
2167 CreateAndSetRemoteOfferAndLocalAnswer();
2168
2169 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2170 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2171 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2172 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2173 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2174}
2175
2176// This test verifies the call setup when remote answer with video only and
2177// later updates with audio.
2178TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002179 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002180 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2181 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2182 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002183 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184
2185 cricket::MediaSessionOptions options;
2186 options.has_audio = false;
2187 options.has_video = true;
2188 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2189 offer, options, cricket::SEC_ENABLED);
2190
2191 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2192 // and answer.
2193 SetLocalDescriptionWithoutError(offer);
2194 SetRemoteDescriptionWithoutError(answer);
2195
2196 video_channel_ = media_engine_->GetVideoChannel(0);
2197 voice_channel_ = media_engine_->GetVoiceChannel(0);
2198
2199 ASSERT_TRUE(voice_channel_ == NULL);
2200 ASSERT_TRUE(video_channel_ != NULL);
2201
2202 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2203 ASSERT_EQ(1u, video_channel_->send_streams().size());
2204 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2205
2206 // Update the session descriptions, with Audio and Video.
2207 mediastream_signaling_.SendAudioVideoStream2();
2208 CreateAndSetRemoteOfferAndLocalAnswer();
2209
2210 voice_channel_ = media_engine_->GetVoiceChannel(0);
2211 ASSERT_TRUE(voice_channel_ != NULL);
2212
2213 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2214 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2215 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2216 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2217
2218 // Change session back to video only.
2219 mediastream_signaling_.UseOptionsVideoOnly();
2220 CreateAndSetRemoteOfferAndLocalAnswer();
2221
2222 video_channel_ = media_engine_->GetVideoChannel(0);
2223 voice_channel_ = media_engine_->GetVoiceChannel(0);
2224
2225 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2226 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2227 ASSERT_EQ(1u, video_channel_->send_streams().size());
2228 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2229}
2230
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002231TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002232 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233 mediastream_signaling_.SendAudioVideoStream1();
2234 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002235 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 VerifyCryptoParams(offer->description());
2237 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002238 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 VerifyCryptoParams(answer->description());
2240}
2241
2242TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002243 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002244 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 mediastream_signaling_.SendAudioVideoStream1();
2246 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002247 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248 VerifyNoCryptoParams(offer->description(), false);
2249}
2250
2251TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002252 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002253 VerifyAnswerFromNonCryptoOffer();
2254}
2255
2256TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002257 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258 VerifyAnswerFromCryptoOffer();
2259}
2260
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002261// This test verifies that setLocalDescription fails if
2262// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2263TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
2264 Init(NULL);
2265 mediastream_signaling_.SendAudioVideoStream1();
2266 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2267 std::string sdp;
2268 RemoveIceUfragPwdLines(offer.get(), &sdp);
2269 SessionDescriptionInterface* modified_offer =
2270 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002271 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002272}
2273
2274// This test verifies that setRemoteDescription fails if
2275// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2276TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
2277 Init(NULL);
2278 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2279 std::string sdp;
2280 RemoveIceUfragPwdLines(offer.get(), &sdp);
2281 SessionDescriptionInterface* modified_offer =
2282 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002283 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002284}
2285
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002286// This test verifies that setLocalDescription fails if local offer has
2287// too short ice ufrag and pwd strings.
2288TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) {
2289 Init(NULL);
2290 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
2291 mediastream_signaling_.SendAudioVideoStream1();
2292 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2293 std::string sdp;
2294 // Modifying ice ufrag and pwd in local offer with strings smaller than the
2295 // recommended values of 4 and 22 bytes respectively.
2296 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2297 SessionDescriptionInterface* modified_offer =
2298 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2299 std::string error;
2300 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2301
2302 // Test with string greater than 256.
2303 sdp.clear();
2304 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2305 &sdp);
2306 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2307 NULL);
2308 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2309}
2310
2311// This test verifies that setRemoteDescription fails if remote offer has
2312// too short ice ufrag and pwd strings.
2313TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) {
2314 Init(NULL);
2315 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
2316 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2317 std::string sdp;
2318 // Modifying ice ufrag and pwd in remote offer with strings smaller than the
2319 // recommended values of 4 and 22 bytes respectively.
2320 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2321 SessionDescriptionInterface* modified_offer =
2322 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2323 std::string error;
2324 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2325
2326 sdp.clear();
2327 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2328 &sdp);
2329 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2330 NULL);
2331 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2332}
2333
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002334TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
2335 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
2336 // local description is removed by the application, BUNDLE flag should be
2337 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00002338 Init(NULL);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002339 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2340 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002341 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002342 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002343 cricket::SessionDescription* offer_copy =
2344 offer->description()->Copy();
2345 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2346 JsepSessionDescription* modified_offer =
2347 new JsepSessionDescription(JsepSessionDescription::kOffer);
2348 modified_offer->Initialize(offer_copy, "1", "1");
2349
2350 SetLocalDescriptionWithoutError(modified_offer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002351 EXPECT_FALSE(allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352}
2353
2354TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002355 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002357 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2358 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002359 FakeConstraints constraints;
2360 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002361 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002362 SetLocalDescriptionWithoutError(offer);
2363 mediastream_signaling_.SendAudioVideoStream2();
2364 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2365 CreateRemoteAnswer(session_->local_description()));
2366 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2367 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2368 JsepSessionDescription* modified_answer =
2369 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2370 modified_answer->Initialize(answer_copy, "1", "1");
2371 SetRemoteDescriptionWithoutError(modified_answer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002372 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2373 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002374
2375 video_channel_ = media_engine_->GetVideoChannel(0);
2376 voice_channel_ = media_engine_->GetVoiceChannel(0);
2377
2378 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2379 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
2380
2381 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2382 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
2383
2384 ASSERT_EQ(1u, video_channel_->send_streams().size());
2385 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
2386 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2387 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
2388}
2389
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002390// This test verifies that SetLocalDescription and SetRemoteDescription fails
2391// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2392TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002393 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002394 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002395 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2396 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002397 FakeConstraints constraints;
2398 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002399 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002400 std::string offer_str;
2401 offer->ToString(&offer_str);
2402 // Disable rtcp-mux
2403 const std::string rtcp_mux = "rtcp-mux";
2404 const std::string xrtcp_mux = "xrtcp-mux";
2405 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
2406 xrtcp_mux.c_str(), xrtcp_mux.length(),
2407 &offer_str);
2408 JsepSessionDescription *local_offer =
2409 new JsepSessionDescription(JsepSessionDescription::kOffer);
2410 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002411 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002412 JsepSessionDescription *remote_offer =
2413 new JsepSessionDescription(JsepSessionDescription::kOffer);
2414 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002415 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002416 // Trying unmodified SDP.
2417 SetLocalDescriptionWithoutError(offer);
2418}
2419
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002420TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002421 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002422 mediastream_signaling_.SendAudioVideoStream1();
2423 CreateAndSetRemoteOfferAndLocalAnswer();
2424 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2425 ASSERT_TRUE(channel != NULL);
2426 ASSERT_EQ(1u, channel->recv_streams().size());
2427 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2428 double left_vol, right_vol;
2429 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2430 EXPECT_EQ(1, left_vol);
2431 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002432 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2433 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002434 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2435 EXPECT_EQ(0, left_vol);
2436 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002437 EXPECT_EQ(0, renderer->channel_id());
2438 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002439 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2440 EXPECT_EQ(1, left_vol);
2441 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002442 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002443}
2444
2445TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002446 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002447 mediastream_signaling_.SendAudioVideoStream1();
2448 CreateAndSetRemoteOfferAndLocalAnswer();
2449 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2450 ASSERT_TRUE(channel != NULL);
2451 ASSERT_EQ(1u, channel->send_streams().size());
2452 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2453 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2454
2455 cricket::AudioOptions options;
2456 options.echo_cancellation.Set(true);
2457
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002458 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2459 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002460 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2461 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002462 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002463 EXPECT_TRUE(renderer->sink() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002464
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002465 // This will trigger SetSink(NULL) to the |renderer|.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002466 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002467 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2468 bool value;
2469 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2470 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002471 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002472 EXPECT_TRUE(renderer->sink() == NULL);
2473}
2474
2475TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) {
2476 Init(NULL);
2477 mediastream_signaling_.SendAudioVideoStream1();
2478 CreateAndSetRemoteOfferAndLocalAnswer();
2479 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2480 ASSERT_TRUE(channel != NULL);
2481 ASSERT_EQ(1u, channel->send_streams().size());
2482 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2483
2484 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2485 cricket::AudioOptions options;
2486 session_->SetAudioSend(send_ssrc, true, options, renderer.get());
2487 EXPECT_TRUE(renderer->sink() != NULL);
2488
2489 // Delete the |renderer| and it will trigger OnClose() to the sink, and this
2490 // will invalidate the |renderer_| pointer in the sink and prevent getting a
2491 // SetSink(NULL) callback afterwards.
2492 renderer.reset();
2493
2494 // This will trigger SetSink(NULL) if no OnClose() callback.
2495 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002496}
2497
2498TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002499 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002500 mediastream_signaling_.SendAudioVideoStream1();
2501 CreateAndSetRemoteOfferAndLocalAnswer();
2502 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2503 ASSERT_TRUE(channel != NULL);
2504 ASSERT_LT(0u, channel->renderers().size());
2505 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2506 ASSERT_EQ(1u, channel->recv_streams().size());
2507 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2508 cricket::FakeVideoRenderer renderer;
2509 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2510 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2511 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2512 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2513}
2514
2515TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002516 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002517 mediastream_signaling_.SendAudioVideoStream1();
2518 CreateAndSetRemoteOfferAndLocalAnswer();
2519 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2520 ASSERT_TRUE(channel != NULL);
2521 ASSERT_EQ(1u, channel->send_streams().size());
2522 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2523 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2524 cricket::VideoOptions* options = NULL;
2525 session_->SetVideoSend(send_ssrc, false, options);
2526 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2527 session_->SetVideoSend(send_ssrc, true, options);
2528 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2529}
2530
2531TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2532 TestCanInsertDtmf(false);
2533}
2534
2535TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2536 TestCanInsertDtmf(true);
2537}
2538
2539TEST_F(WebRtcSessionTest, InsertDtmf) {
2540 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002541 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002542 mediastream_signaling_.SendAudioVideoStream1();
2543 CreateAndSetRemoteOfferAndLocalAnswer();
2544 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2545 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2546
2547 // Insert DTMF
2548 const int expected_flags = DF_SEND;
2549 const int expected_duration = 90;
2550 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2551 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2552 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2553
2554 // Verify
2555 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2556 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2557 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2558 expected_duration, expected_flags));
2559 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2560 expected_duration, expected_flags));
2561 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2562 expected_duration, expected_flags));
2563}
2564
2565// This test verifies the |initiator| flag when session initiates the call.
2566TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002567 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002568 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002569 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002570 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2571 SetLocalDescriptionWithoutError(offer);
2572 EXPECT_TRUE(session_->initiator());
2573 SetRemoteDescriptionWithoutError(answer);
2574 EXPECT_TRUE(session_->initiator());
2575}
2576
2577// This test verifies the |initiator| flag when session receives the call.
2578TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002579 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002580 EXPECT_FALSE(session_->initiator());
2581 SessionDescriptionInterface* offer = CreateRemoteOffer();
2582 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002583 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002584
2585 EXPECT_FALSE(session_->initiator());
2586 SetLocalDescriptionWithoutError(answer);
2587 EXPECT_FALSE(session_->initiator());
2588}
2589
2590// This test verifies the ice protocol type at initiator of the call
2591// if |a=ice-options:google-ice| is present in answer.
2592TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002593 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002594 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002595 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002596 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002597 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002598 SetLocalDescriptionWithoutError(offer);
2599 std::string sdp;
2600 EXPECT_TRUE(answer->ToString(&sdp));
2601 // Adding ice-options to the session level.
2602 InjectAfter("t=0 0\r\n",
2603 "a=ice-options:google-ice\r\n",
2604 &sdp);
2605 SessionDescriptionInterface* answer_with_gice =
2606 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2607 SetRemoteDescriptionWithoutError(answer_with_gice);
2608 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2609 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2610}
2611
2612// This test verifies the ice protocol type at initiator of the call
2613// if ICE RFC5245 is supported in answer.
2614TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002615 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002616 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002617 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002618 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2619 SetLocalDescriptionWithoutError(offer);
2620
2621 SetRemoteDescriptionWithoutError(answer);
2622 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2623 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2624}
2625
2626// This test verifies the ice protocol type at receiver side of the call if
2627// receiver decides to use google-ice.
2628TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002629 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002630 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002631 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002632 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002633 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002634 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002635 std::string sdp;
2636 EXPECT_TRUE(answer->ToString(&sdp));
2637 // Adding ice-options to the session level.
2638 InjectAfter("t=0 0\r\n",
2639 "a=ice-options:google-ice\r\n",
2640 &sdp);
2641 SessionDescriptionInterface* answer_with_gice =
2642 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2643 SetLocalDescriptionWithoutError(answer_with_gice);
2644 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2645 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2646}
2647
2648// This test verifies the ice protocol type at receiver side of the call if
2649// receiver decides to use ice RFC 5245.
2650TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002651 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002652 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002653 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002654 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002655 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002656 SetLocalDescriptionWithoutError(answer);
2657 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2658 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2659}
2660
2661// This test verifies the session state when ICE RFC5245 in offer and
2662// ICE google-ice in answer.
2663TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002664 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002665 mediastream_signaling_.SendAudioVideoStream1();
2666 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002667 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002668 std::string offer_str;
2669 offer->ToString(&offer_str);
2670 // Disable google-ice
2671 const std::string gice_option = "google-ice";
2672 const std::string xgoogle_xice = "xgoogle-xice";
2673 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2674 xgoogle_xice.c_str(), xgoogle_xice.length(),
2675 &offer_str);
2676 JsepSessionDescription *ice_only_offer =
2677 new JsepSessionDescription(JsepSessionDescription::kOffer);
2678 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2679 SetLocalDescriptionWithoutError(ice_only_offer);
2680 std::string original_offer_sdp;
2681 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002682 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002683 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002684 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002685 SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
2686 pranswer_with_gice);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002687 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002688 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002689 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002690 SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
2691 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002692}
2693
2694// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2695TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002696 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002697 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002698 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002699 SetLocalDescriptionWithoutError(offer);
2700 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2701 CreateRemoteAnswer(session_->local_description()));
2702
2703 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2704 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002705 JsepSessionDescription* modified_answer =
2706 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002707
2708 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2709 answer->session_id(),
2710 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002711 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002712
wu@webrtc.org4e393072014-04-07 17:04:35 +00002713 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002714 std::string sdp;
2715 EXPECT_TRUE(answer->ToString(&sdp));
2716 const std::string kAudioMid = "a=mid:audio";
2717 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002718 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2719 kAudioMidReplaceStr.c_str(),
2720 kAudioMidReplaceStr.length(),
2721 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002722 SessionDescriptionInterface* modified_answer1 =
2723 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002724 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002725
wu@webrtc.org4e393072014-04-07 17:04:35 +00002726 // Different media types.
2727 EXPECT_TRUE(answer->ToString(&sdp));
2728 const std::string kAudioMline = "m=audio";
2729 const std::string kAudioMlineReplaceStr = "m=video";
2730 talk_base::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
2731 kAudioMlineReplaceStr.c_str(),
2732 kAudioMlineReplaceStr.length(),
2733 &sdp);
2734 SessionDescriptionInterface* modified_answer2 =
2735 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2736 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
2737
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002738 SetRemoteDescriptionWithoutError(answer.release());
2739}
2740
2741// Verifying remote offer and local answer have matching m-lines as per
2742// RFC 3264.
2743TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002744 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002745 mediastream_signaling_.SendAudioVideoStream1();
2746 SessionDescriptionInterface* offer = CreateRemoteOffer();
2747 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002748 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002749
2750 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2751 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002752 JsepSessionDescription* modified_answer =
2753 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002754
2755 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2756 answer->session_id(),
2757 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002758 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002759 SetLocalDescriptionWithoutError(answer);
2760}
2761
2762// This test verifies that WebRtcSession does not start candidate allocation
2763// before SetLocalDescription is called.
2764TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002765 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002766 mediastream_signaling_.SendAudioVideoStream1();
2767 SessionDescriptionInterface* offer = CreateRemoteOffer();
2768 cricket::Candidate candidate;
2769 candidate.set_component(1);
2770 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2771 candidate);
2772 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2773 cricket::Candidate candidate1;
2774 candidate1.set_component(1);
2775 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2776 candidate1);
2777 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2778 SetRemoteDescriptionWithoutError(offer);
2779 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2780 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2781
2782 // Pump for 1 second and verify that no candidates are generated.
2783 talk_base::Thread::Current()->ProcessMessages(1000);
2784 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2785 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2786
wu@webrtc.org91053e72013-08-10 07:18:04 +00002787 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002788 SetLocalDescriptionWithoutError(answer);
2789 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2790 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2791 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2792}
2793
2794// This test verifies that crypto parameter is updated in local session
2795// description as per security policy set in MediaSessionDescriptionFactory.
2796TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002797 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002798 mediastream_signaling_.SendAudioVideoStream1();
2799 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002800 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002801
2802 // Making sure SetLocalDescription correctly sets crypto value in
2803 // SessionDescription object after de-serialization of sdp string. The value
2804 // will be set as per MediaSessionDescriptionFactory.
2805 std::string offer_str;
2806 offer->ToString(&offer_str);
2807 SessionDescriptionInterface* jsep_offer_str =
2808 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2809 SetLocalDescriptionWithoutError(jsep_offer_str);
2810 EXPECT_TRUE(session_->voice_channel()->secure_required());
2811 EXPECT_TRUE(session_->video_channel()->secure_required());
2812}
2813
2814// This test verifies the crypto parameter when security is disabled.
2815TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002816 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002817 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002818 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002819 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002820 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002821
2822 // Making sure SetLocalDescription correctly sets crypto value in
2823 // SessionDescription object after de-serialization of sdp string. The value
2824 // will be set as per MediaSessionDescriptionFactory.
2825 std::string offer_str;
2826 offer->ToString(&offer_str);
2827 SessionDescriptionInterface *jsep_offer_str =
2828 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2829 SetLocalDescriptionWithoutError(jsep_offer_str);
2830 EXPECT_FALSE(session_->voice_channel()->secure_required());
2831 EXPECT_FALSE(session_->video_channel()->secure_required());
2832}
2833
2834// This test verifies that an answer contains new ufrag and password if an offer
2835// with new ufrag and password is received.
2836TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002837 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002838 cricket::MediaSessionOptions options;
2839 options.has_audio = true;
2840 options.has_video = true;
2841 talk_base::scoped_ptr<JsepSessionDescription> offer(
2842 CreateRemoteOffer(options));
2843 SetRemoteDescriptionWithoutError(offer.release());
2844
2845 mediastream_signaling_.SendAudioVideoStream1();
2846 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002847 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002848 SetLocalDescriptionWithoutError(answer.release());
2849
2850 // Receive an offer with new ufrag and password.
2851 options.transport_options.ice_restart = true;
2852 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002853 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002854 SetRemoteDescriptionWithoutError(updated_offer1.release());
2855
2856 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002857 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002858
2859 CompareIceUfragAndPassword(updated_answer1->description(),
2860 session_->local_description()->description(),
2861 false);
2862
2863 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002864}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002865
wu@webrtc.org91053e72013-08-10 07:18:04 +00002866// This test verifies that an answer contains old ufrag and password if an offer
2867// with old ufrag and password is received.
2868TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2869 Init(NULL);
2870 cricket::MediaSessionOptions options;
2871 options.has_audio = true;
2872 options.has_video = true;
2873 talk_base::scoped_ptr<JsepSessionDescription> offer(
2874 CreateRemoteOffer(options));
2875 SetRemoteDescriptionWithoutError(offer.release());
2876
2877 mediastream_signaling_.SendAudioVideoStream1();
2878 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2879 CreateAnswer(NULL));
2880 SetLocalDescriptionWithoutError(answer.release());
2881
2882 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002883 options.transport_options.ice_restart = false;
2884 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002885 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002886 SetRemoteDescriptionWithoutError(updated_offer2.release());
2887
2888 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002889 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002890
2891 CompareIceUfragAndPassword(updated_answer2->description(),
2892 session_->local_description()->description(),
2893 true);
2894
2895 SetLocalDescriptionWithoutError(updated_answer2.release());
2896}
2897
2898TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002899 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002900 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002901 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002902 const std::string session_id_orig = offer->session_id();
2903 const std::string session_version_orig = offer->session_version();
2904 SetLocalDescriptionWithoutError(offer);
2905
2906 video_channel_ = media_engine_->GetVideoChannel(0);
2907 video_channel_->set_fail_set_send_codecs(true);
2908
2909 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002910 SessionDescriptionInterface* answer =
2911 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002912 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002913}
2914
2915// Runs the loopback call test with BUNDLE and STUN disabled.
2916TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2917 // Lets try with only UDP ports.
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002918 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002919 cricket::PORTALLOCATOR_DISABLE_TCP |
2920 cricket::PORTALLOCATOR_DISABLE_STUN |
2921 cricket::PORTALLOCATOR_DISABLE_RELAY);
2922 TestLoopbackCall();
2923}
2924
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002925// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002926TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002927 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002928 cricket::PORTALLOCATOR_ENABLE_BUNDLE |
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002929 cricket::PORTALLOCATOR_DISABLE_TCP |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002930 cricket::PORTALLOCATOR_DISABLE_RELAY);
2931 TestLoopbackCall();
2932}
2933
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002934TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002935 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002936 cricket::MediaSessionOptions options;
2937 options.has_audio = true;
2938 options.has_video = true;
2939
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002940 cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
2941 std::string error_code_str = "ERROR_CONTENT";
2942 std::string error_desc = "Fake session error description.";
2943 session_->SetError(error_code, error_desc);
2944
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002945 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2946 SessionDescriptionInterface* answer =
2947 CreateRemoteAnswer(offer, options);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002948
2949 std::string action;
2950 std::ostringstream session_error_msg;
2951 session_error_msg << kSessionError << error_code_str << ". ";
2952 session_error_msg << kSessionErrorDesc << error_desc << ".";
2953 SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
2954 SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002955}
2956
2957TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2958 constraints_.reset(new FakeConstraints());
2959 constraints_->AddOptional(
2960 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002961 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002962
2963 SetLocalDescriptionWithDataChannel();
2964 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2965}
2966
2967TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2968 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2969
2970 constraints_.reset(new FakeConstraints());
2971 constraints_->AddOptional(
2972 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org97077a32013-10-25 21:18:33 +00002973 options_.disable_sctp_data_channels = false;
2974
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002975 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002976
2977 SetLocalDescriptionWithDataChannel();
2978 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2979}
2980
wu@webrtc.org967bfff2013-09-19 05:49:50 +00002981TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2982 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2983
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002984 InitWithDtls();
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002985
2986 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2987 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002988 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2989}
2990
2991TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2992 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2993 SetFactoryDtlsSrtp();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002994 InitWithDtls();
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002995
2996 // Create remote offer with SCTP.
2997 cricket::MediaSessionOptions options;
2998 options.data_channel_type = cricket::DCT_SCTP;
2999 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003000 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003001 SetRemoteDescriptionWithoutError(offer);
3002
3003 // Verifies the answer contains SCTP.
3004 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
3005 EXPECT_TRUE(answer != NULL);
3006 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
3007 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003008}
3009
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003010TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
3011 constraints_.reset(new FakeConstraints());
3012 constraints_->AddOptional(
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003013 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003014 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003015
3016 SetLocalDescriptionWithDataChannel();
3017 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3018}
3019
3020TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
3021 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3022
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003023 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003024
3025 SetLocalDescriptionWithDataChannel();
3026 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3027}
wu@webrtc.org91053e72013-08-10 07:18:04 +00003028
wu@webrtc.org97077a32013-10-25 21:18:33 +00003029TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
3030 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3031 options_.disable_sctp_data_channels = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003032 InitWithDtls();
wu@webrtc.org97077a32013-10-25 21:18:33 +00003033
3034 SetLocalDescriptionWithDataChannel();
3035 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3036}
3037
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003038TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
3039 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3040 const int new_send_port = 9998;
3041 const int new_recv_port = 7775;
3042
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003043 InitWithDtls();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003044 SetFactoryDtlsSrtp();
3045
3046 // By default, don't actually add the codecs to desc_factory_; they don't
3047 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
3048 // let the session description get parsed. That'll get the proper codecs
3049 // into the stream.
3050 cricket::MediaSessionOptions options;
3051 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
3052 "stream1", new_send_port, options);
3053
3054 // SetRemoteDescription will take the ownership of the offer.
3055 SetRemoteDescriptionWithoutError(offer);
3056
3057 SessionDescriptionInterface* answer = ChangeSDPSctpPort(
3058 new_recv_port, CreateAnswer(NULL));
3059 ASSERT_TRUE(answer != NULL);
3060
3061 // Now set the local description, which'll take ownership of the answer.
3062 SetLocalDescriptionWithoutError(answer);
3063
3064 // TEST PLAN: Set the port number to something new, set it in the SDP,
3065 // and pass it all the way down.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00003066 webrtc::InternalDataChannelInit dci;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003067 dci.reliable = true;
3068 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3069 talk_base::scoped_refptr<webrtc::DataChannel> dc =
3070 session_->CreateDataChannel("datachannel", &dci);
3071
3072 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
3073 int portnum = -1;
3074 ASSERT_TRUE(ch != NULL);
3075 ASSERT_EQ(1UL, ch->send_codecs().size());
3076 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
3077 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3078 ch->send_codecs()[0].name.c_str()));
3079 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
3080 &portnum));
3081 EXPECT_EQ(new_send_port, portnum);
3082
3083 ASSERT_EQ(1UL, ch->recv_codecs().size());
3084 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
3085 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3086 ch->recv_codecs()[0].name.c_str()));
3087 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
3088 &portnum));
3089 EXPECT_EQ(new_recv_port, portnum);
3090}
3091
wu@webrtc.org91053e72013-08-10 07:18:04 +00003092// Verifies that CreateOffer succeeds when CreateOffer is called before async
3093// identity generation is finished.
3094TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
3095 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003096 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003097
3098 EXPECT_TRUE(session_->waiting_for_identity());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003099 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003100 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3101 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003102 VerifyNoCryptoParams(offer->description(), true);
3103 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003104}
3105
3106// Verifies that CreateAnswer succeeds when CreateOffer is called before async
3107// identity generation is finished.
3108TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
3109 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003110 InitWithDtls();
3111 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003112
3113 cricket::MediaSessionOptions options;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003114 options.has_video = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003115 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003116 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003117 ASSERT_TRUE(offer.get() != NULL);
3118 SetRemoteDescriptionWithoutError(offer.release());
3119
3120 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
3121 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003122 VerifyNoCryptoParams(answer->description(), true);
3123 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003124}
3125
3126// Verifies that CreateOffer succeeds when CreateOffer is called after async
3127// identity generation is finished.
3128TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
3129 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003130 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003131
3132 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3133 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3134 EXPECT_TRUE(offer != NULL);
3135}
3136
3137// Verifies that CreateOffer fails when CreateOffer is called after async
3138// identity generation fails.
3139TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
3140 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00003141 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003142
3143 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3144 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3145 EXPECT_TRUE(offer == NULL);
3146}
3147
3148// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
3149// before async identity generation is finished.
3150TEST_F(WebRtcSessionTest,
3151 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
3152 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3153 VerifyMultipleAsyncCreateDescription(
3154 true, CreateSessionDescriptionRequest::kOffer);
3155}
3156
3157// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
3158// before async identity generation fails.
3159TEST_F(WebRtcSessionTest,
3160 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
3161 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3162 VerifyMultipleAsyncCreateDescription(
3163 false, CreateSessionDescriptionRequest::kOffer);
3164}
3165
3166// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
3167// before async identity generation is finished.
3168TEST_F(WebRtcSessionTest,
3169 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
3170 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3171 VerifyMultipleAsyncCreateDescription(
3172 true, CreateSessionDescriptionRequest::kAnswer);
3173}
3174
3175// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
3176// before async identity generation fails.
3177TEST_F(WebRtcSessionTest,
3178 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
3179 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3180 VerifyMultipleAsyncCreateDescription(
3181 false, CreateSessionDescriptionRequest::kAnswer);
3182}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003183
3184// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
3185// offer has no SDES crypto but only DTLS fingerprint.
3186TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
3187 // Init without DTLS.
3188 Init(NULL);
3189 // Create a remote offer with secured transport disabled.
3190 cricket::MediaSessionOptions options;
3191 JsepSessionDescription* offer(CreateRemoteOffer(
3192 options, cricket::SEC_DISABLED));
3193 // Adds a DTLS fingerprint to the remote offer.
3194 cricket::SessionDescription* sdp = offer->description();
3195 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
3196 ASSERT_TRUE(audio != NULL);
3197 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
3198 audio->description.identity_fingerprint.reset(
3199 talk_base::SSLFingerprint::CreateFromRfc4572(
3200 talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003201 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003202 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003203}
3204
wu@webrtc.orgde305012013-10-31 15:40:38 +00003205// This test verifies DSCP is properly applied on the media channels.
3206TEST_F(WebRtcSessionTest, TestDscpConstraint) {
3207 constraints_.reset(new FakeConstraints());
3208 constraints_->AddOptional(
3209 webrtc::MediaConstraintsInterface::kEnableDscp, true);
3210 Init(NULL);
3211 mediastream_signaling_.SendAudioVideoStream1();
3212 SessionDescriptionInterface* offer = CreateOffer(NULL);
3213
3214 SetLocalDescriptionWithoutError(offer);
3215
3216 video_channel_ = media_engine_->GetVideoChannel(0);
3217 voice_channel_ = media_engine_->GetVoiceChannel(0);
3218
3219 ASSERT_TRUE(video_channel_ != NULL);
3220 ASSERT_TRUE(voice_channel_ != NULL);
3221 cricket::AudioOptions audio_options;
3222 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
3223 cricket::VideoOptions video_options;
3224 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3225 EXPECT_TRUE(audio_options.dscp.IsSet());
3226 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
3227 EXPECT_TRUE(video_options.dscp.IsSet());
3228 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
3229}
3230
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003231TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) {
3232 constraints_.reset(new FakeConstraints());
3233 constraints_->AddOptional(
3234 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
3235 true);
3236 Init(NULL);
3237 mediastream_signaling_.SendAudioVideoStream1();
3238 SessionDescriptionInterface* offer = CreateOffer(NULL);
3239
3240 SetLocalDescriptionWithoutError(offer);
3241
3242 video_channel_ = media_engine_->GetVideoChannel(0);
3243
3244 ASSERT_TRUE(video_channel_ != NULL);
3245 cricket::VideoOptions video_options;
3246 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3247 EXPECT_TRUE(
3248 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false));
3249}
3250
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003251// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
3252// currently fails because upon disconnection and reconnection OnIceComplete is
3253// called more than once without returning to IceGatheringGathering.