blob: 956f8a66fb24943b70ec7bca425a59dd9d69de30 [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);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108
109static const char kSessionVersion[] = "1";
110
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111// Media index of candidates belonging to the first media content.
112static const int kMediaContentIndex0 = 0;
113static const char kMediaContentName0[] = "audio";
114
115// Media index of candidates belonging to the second media content.
116static const int kMediaContentIndex1 = 1;
117static const char kMediaContentName1[] = "video";
118
119static const int kIceCandidatesTimeout = 10000;
120
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000121static const char kFakeDtlsFingerprint[] =
122 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
123 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
124
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000125static const char kTooLongIceUfragPwd[] =
126 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
127 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
128 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
129 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag";
130
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000131// Add some extra |newlines| to the |message| after |line|.
132static void InjectAfter(const std::string& line,
133 const std::string& newlines,
134 std::string* message) {
135 const std::string tmp = line + newlines;
136 talk_base::replace_substrs(line.c_str(), line.length(),
137 tmp.c_str(), tmp.length(), message);
138}
139
140class MockIceObserver : public webrtc::IceObserver {
141 public:
142 MockIceObserver()
143 : oncandidatesready_(false),
144 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
145 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
146 }
147
148 virtual void OnIceConnectionChange(
149 PeerConnectionInterface::IceConnectionState new_state) {
150 ice_connection_state_ = new_state;
151 }
152 virtual void OnIceGatheringChange(
153 PeerConnectionInterface::IceGatheringState new_state) {
154 // We can never transition back to "new".
155 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
156 ice_gathering_state_ = new_state;
157
158 // oncandidatesready_ really means "ICE gathering is complete".
159 // This if statement ensures that this value remains correct when we
160 // transition from kIceGatheringComplete to kIceGatheringGathering.
161 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
162 oncandidatesready_ = false;
163 }
164 }
165
166 // Found a new candidate.
167 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000168 switch (candidate->sdp_mline_index()) {
169 case kMediaContentIndex0:
170 mline_0_candidates_.push_back(candidate->candidate());
171 break;
172 case kMediaContentIndex1:
173 mline_1_candidates_.push_back(candidate->candidate());
174 break;
175 default:
176 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000177 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000178
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000179 // The ICE gathering state should always be Gathering when a candidate is
180 // received (or possibly Completed in the case of the final candidate).
181 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
182 }
183
184 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
185 virtual void OnIceComplete() {
186 EXPECT_FALSE(oncandidatesready_);
187 oncandidatesready_ = true;
188
189 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
190 // be called approximately simultaneously. For ease of testing, this
191 // check additionally requires that they be called in the above order.
192 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
193 ice_gathering_state_);
194 }
195
196 bool oncandidatesready_;
197 std::vector<cricket::Candidate> mline_0_candidates_;
198 std::vector<cricket::Candidate> mline_1_candidates_;
199 PeerConnectionInterface::IceConnectionState ice_connection_state_;
200 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
201};
202
203class WebRtcSessionForTest : public webrtc::WebRtcSession {
204 public:
205 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
206 talk_base::Thread* signaling_thread,
207 talk_base::Thread* worker_thread,
208 cricket::PortAllocator* port_allocator,
209 webrtc::IceObserver* ice_observer,
210 webrtc::MediaStreamSignaling* mediastream_signaling)
211 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
212 mediastream_signaling) {
213 RegisterIceObserver(ice_observer);
214 }
215 virtual ~WebRtcSessionForTest() {}
216
217 using cricket::BaseSession::GetTransportProxy;
218 using webrtc::WebRtcSession::SetAudioPlayout;
219 using webrtc::WebRtcSession::SetAudioSend;
220 using webrtc::WebRtcSession::SetCaptureDevice;
221 using webrtc::WebRtcSession::SetVideoPlayout;
222 using webrtc::WebRtcSession::SetVideoSend;
223};
224
wu@webrtc.org91053e72013-08-10 07:18:04 +0000225class WebRtcSessionCreateSDPObserverForTest
226 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000228 enum State {
229 kInit,
230 kFailed,
231 kSucceeded,
232 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000233 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000234
235 // CreateSessionDescriptionObserver implementation.
236 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000237 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000238 state_ = kSucceeded;
239 }
240 virtual void OnFailure(const std::string& error) {
241 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000242 }
243
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000244 SessionDescriptionInterface* description() { return description_.get(); }
245
246 SessionDescriptionInterface* ReleaseDescription() {
247 return description_.release();
248 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000249
wu@webrtc.org91053e72013-08-10 07:18:04 +0000250 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251
wu@webrtc.org91053e72013-08-10 07:18:04 +0000252 protected:
253 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000254
255 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000256 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000257 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258};
259
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000260class FakeAudioRenderer : public cricket::AudioRenderer {
261 public:
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000262 FakeAudioRenderer() : channel_id_(-1), sink_(NULL) {}
263 virtual ~FakeAudioRenderer() {
264 if (sink_)
265 sink_->OnClose();
266 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000267
268 virtual void AddChannel(int channel_id) OVERRIDE {
269 ASSERT(channel_id_ == -1);
270 channel_id_ = channel_id;
271 }
272 virtual void RemoveChannel(int channel_id) OVERRIDE {
273 ASSERT(channel_id == channel_id_);
274 channel_id_ = -1;
275 }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000276 virtual void SetSink(Sink* sink) OVERRIDE {
277 sink_ = sink;
278 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000279
280 int channel_id() const { return channel_id_; }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000281 cricket::AudioRenderer::Sink* sink() const { return sink_; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000282 private:
283 int channel_id_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000284 cricket::AudioRenderer::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000285};
286
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287class WebRtcSessionTest : public testing::Test {
288 protected:
289 // TODO Investigate why ChannelManager crashes, if it's created
290 // after stun_server.
291 WebRtcSessionTest()
292 : media_engine_(new cricket::FakeMediaEngine()),
293 data_engine_(new cricket::FakeDataEngine()),
294 device_manager_(new cricket::FakeDeviceManager()),
295 channel_manager_(new cricket::ChannelManager(
296 media_engine_, data_engine_, device_manager_,
297 new cricket::CaptureManager(), talk_base::Thread::Current())),
298 tdesc_factory_(new cricket::TransportDescriptionFactory()),
299 desc_factory_(new cricket::MediaSessionDescriptionFactory(
300 channel_manager_.get(), tdesc_factory_.get())),
301 pss_(new talk_base::PhysicalSocketServer),
302 vss_(new talk_base::VirtualSocketServer(pss_.get())),
303 fss_(new talk_base::FirewallSocketServer(vss_.get())),
304 ss_scope_(fss_.get()),
wu@webrtc.org364f2042013-11-20 21:49:41 +0000305 stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
306 cricket::STUN_SERVER_PORT)),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000307 stun_server_(Thread::Current(), stun_socket_addr_),
308 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
309 allocator_(new cricket::BasicPortAllocator(
310 &network_manager_, stun_socket_addr_,
311 SocketAddress(), SocketAddress(), SocketAddress())),
312 mediastream_signaling_(channel_manager_.get()),
313 ice_type_(PeerConnectionInterface::kAll) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000315 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316 cricket::PORTALLOCATOR_DISABLE_RELAY |
317 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
318 EXPECT_TRUE(channel_manager_->Init());
319 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000320 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 }
322
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000323 static void SetUpTestCase() {
324 talk_base::InitializeSSL();
325 }
326
327 static void TearDownTestCase() {
328 talk_base::CleanupSSL();
329 }
330
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000331 void AddInterface(const SocketAddress& addr) {
332 network_manager_.AddInterface(addr);
333 }
334
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000335 void SetIceTransportType(PeerConnectionInterface::IceTransportsType type) {
336 ice_type_ = type;
337 }
338
wu@webrtc.org91053e72013-08-10 07:18:04 +0000339 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000340 ASSERT_TRUE(session_.get() == NULL);
341 session_.reset(new WebRtcSessionForTest(
342 channel_manager_.get(), talk_base::Thread::Current(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000343 talk_base::Thread::Current(), allocator_.get(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344 &observer_,
345 &mediastream_signaling_));
346
347 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
348 observer_.ice_connection_state_);
349 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
350 observer_.ice_gathering_state_);
351
wu@webrtc.org97077a32013-10-25 21:18:33 +0000352 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000353 identity_service, ice_type_));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000354 }
355
356 void InitWithDtmfCodec() {
357 // Add kTelephoneEventCodec for dtmf test.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000358 const cricket::AudioCodec kTelephoneEventCodec(
359 106, "telephone-event", 8000, 0, 1, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000360 std::vector<cricket::AudioCodec> codecs;
361 codecs.push_back(kTelephoneEventCodec);
362 media_engine_->SetAudioCodecs(codecs);
363 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000364 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 }
366
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000367 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000368 FakeIdentityService* identity_service = new FakeIdentityService();
369 identity_service->set_should_fail(identity_request_should_fail);
370 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000371 }
372
373 // Creates a local offer and applies it. Starts ice.
374 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
375 // to decide which streams to create.
376 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000377 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 SetLocalDescriptionWithoutError(offer);
379 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
380 observer_.ice_gathering_state_,
381 kIceCandidatesTimeout);
382 }
383
wu@webrtc.org91053e72013-08-10 07:18:04 +0000384 SessionDescriptionInterface* CreateOffer(
385 const webrtc::MediaConstraintsInterface* constraints) {
386 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
387 observer = new WebRtcSessionCreateSDPObserverForTest();
388 session_->CreateOffer(observer, constraints);
389 EXPECT_TRUE_WAIT(
390 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000391 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000392 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000393 }
394
395 SessionDescriptionInterface* CreateAnswer(
396 const webrtc::MediaConstraintsInterface* constraints) {
397 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
398 = new WebRtcSessionCreateSDPObserverForTest();
399 session_->CreateAnswer(observer, constraints);
400 EXPECT_TRUE_WAIT(
401 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000402 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000403 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000404 }
405
wu@webrtc.org364f2042013-11-20 21:49:41 +0000406 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 return (session_->voice_channel() != NULL &&
408 session_->video_channel() != NULL);
409 }
410
wu@webrtc.org364f2042013-11-20 21:49:41 +0000411 void CheckTransportChannels() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
413 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
414 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
415 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
416 }
417
418 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
419 ASSERT_TRUE(session_.get() != NULL);
420 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
421 ASSERT_TRUE(content != NULL);
422 const cricket::AudioContentDescription* audio_content =
423 static_cast<const cricket::AudioContentDescription*>(
424 content->description);
425 ASSERT_TRUE(audio_content != NULL);
426 ASSERT_EQ(1U, audio_content->cryptos().size());
427 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
428 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
429 audio_content->cryptos()[0].cipher_suite);
430 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
431 audio_content->protocol());
432
433 content = cricket::GetFirstVideoContent(sdp);
434 ASSERT_TRUE(content != NULL);
435 const cricket::VideoContentDescription* video_content =
436 static_cast<const cricket::VideoContentDescription*>(
437 content->description);
438 ASSERT_TRUE(video_content != NULL);
439 ASSERT_EQ(1U, video_content->cryptos().size());
440 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
441 video_content->cryptos()[0].cipher_suite);
442 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
443 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
444 video_content->protocol());
445 }
446
447 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
448 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
449 ASSERT_TRUE(content != NULL);
450 const cricket::AudioContentDescription* audio_content =
451 static_cast<const cricket::AudioContentDescription*>(
452 content->description);
453 ASSERT_TRUE(audio_content != NULL);
454 ASSERT_EQ(0U, audio_content->cryptos().size());
455
456 content = cricket::GetFirstVideoContent(sdp);
457 ASSERT_TRUE(content != NULL);
458 const cricket::VideoContentDescription* video_content =
459 static_cast<const cricket::VideoContentDescription*>(
460 content->description);
461 ASSERT_TRUE(video_content != NULL);
462 ASSERT_EQ(0U, video_content->cryptos().size());
463
464 if (dtls) {
465 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
466 audio_content->protocol());
467 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
468 video_content->protocol());
469 } else {
470 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
471 audio_content->protocol());
472 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
473 video_content->protocol());
474 }
475 }
476
477 // Set the internal fake description factories to do DTLS-SRTP.
478 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000479 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000480 std::string identity_name = "WebRTC" +
481 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000482 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
483 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
485 }
486
487 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
488 bool expected) {
489 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
490 ASSERT_TRUE(audio != NULL);
491 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 const TransportInfo* video = sdp->GetTransportInfoByName("video");
493 ASSERT_TRUE(video != NULL);
494 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000495 }
496
497 void VerifyAnswerFromNonCryptoOffer() {
498 // Create a SDP without Crypto.
499 cricket::MediaSessionOptions options;
500 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000501 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000503 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000505 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
506 offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000507 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508 // Answer should be NULL as no crypto params in offer.
509 ASSERT_TRUE(answer == NULL);
510 }
511
512 void VerifyAnswerFromCryptoOffer() {
513 cricket::MediaSessionOptions options;
514 options.has_video = true;
515 options.bundle_enabled = true;
516 scoped_ptr<JsepSessionDescription> offer(
517 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
518 ASSERT_TRUE(offer.get() != NULL);
519 VerifyCryptoParams(offer->description());
520 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000521 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 ASSERT_TRUE(answer.get() != NULL);
523 VerifyCryptoParams(answer->description());
524 }
525
526 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
527 const cricket::SessionDescription* desc2,
528 bool expect_equal) {
529 if (desc1->contents().size() != desc2->contents().size()) {
530 EXPECT_FALSE(expect_equal);
531 return;
532 }
533
534 const cricket::ContentInfos& contents = desc1->contents();
535 cricket::ContentInfos::const_iterator it = contents.begin();
536
537 for (; it != contents.end(); ++it) {
538 const cricket::TransportDescription* transport_desc1 =
539 desc1->GetTransportDescriptionByName(it->name);
540 const cricket::TransportDescription* transport_desc2 =
541 desc2->GetTransportDescriptionByName(it->name);
542 if (!transport_desc1 || !transport_desc2) {
543 EXPECT_FALSE(expect_equal);
544 return;
545 }
546 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
547 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
548 EXPECT_FALSE(expect_equal);
549 return;
550 }
551 }
552 EXPECT_TRUE(expect_equal);
553 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000554
555 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
556 std::string *sdp) {
557 const cricket::SessionDescription* desc = current_desc->description();
558 EXPECT_TRUE(current_desc->ToString(sdp));
559
560 const cricket::ContentInfos& contents = desc->contents();
561 cricket::ContentInfos::const_iterator it = contents.begin();
562 // Replace ufrag and pwd lines with empty strings.
563 for (; it != contents.end(); ++it) {
564 const cricket::TransportDescription* transport_desc =
565 desc->GetTransportDescriptionByName(it->name);
566 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
567 + "\r\n";
568 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
569 + "\r\n";
570 talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
571 "", 0,
572 sdp);
573 talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
574 "", 0,
575 sdp);
576 }
577 }
578
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000579 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
580 const std::string& modified_ice_ufrag,
581 const std::string& modified_ice_pwd,
582 std::string* sdp) {
583 const cricket::SessionDescription* desc = current_desc->description();
584 EXPECT_TRUE(current_desc->ToString(sdp));
585
586 const cricket::ContentInfos& contents = desc->contents();
587 cricket::ContentInfos::const_iterator it = contents.begin();
588 // Replace ufrag and pwd lines with |modified_ice_ufrag| and
589 // |modified_ice_pwd| strings.
590 for (; it != contents.end(); ++it) {
591 const cricket::TransportDescription* transport_desc =
592 desc->GetTransportDescriptionByName(it->name);
593 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
594 + "\r\n";
595 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
596 + "\r\n";
597 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n";
598 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n";
599 talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
600 mod_ufrag.c_str(), mod_ufrag.length(),
601 sdp);
602 talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
603 mod_pwd.c_str(), mod_pwd.length(),
604 sdp);
605 }
606 }
607
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000608 // Creates a remote offer and and applies it as a remote description,
609 // creates a local answer and applies is as a local description.
610 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
611 // to decide which local and remote streams to create.
612 void CreateAndSetRemoteOfferAndLocalAnswer() {
613 SessionDescriptionInterface* offer = CreateRemoteOffer();
614 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000615 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 SetLocalDescriptionWithoutError(answer);
617 }
618 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
619 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
620 }
621 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
622 BaseSession::State expected_state) {
623 SetLocalDescriptionWithoutError(desc);
624 EXPECT_EQ(expected_state, session_->state());
625 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000626 void SetLocalDescriptionExpectError(const std::string& action,
627 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 SessionDescriptionInterface* desc) {
629 std::string error;
630 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000631 std::string sdp_type = "local ";
632 sdp_type.append(action);
633 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000634 EXPECT_NE(std::string::npos, error.find(expected_error));
635 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000636 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
637 SessionDescriptionInterface* desc) {
638 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
639 expected_error, desc);
640 }
641 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
642 SessionDescriptionInterface* desc) {
643 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
644 expected_error, desc);
645 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
647 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
648 }
649 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
650 BaseSession::State expected_state) {
651 SetRemoteDescriptionWithoutError(desc);
652 EXPECT_EQ(expected_state, session_->state());
653 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000654 void SetRemoteDescriptionExpectError(const std::string& action,
655 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 SessionDescriptionInterface* desc) {
657 std::string error;
658 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000659 std::string sdp_type = "remote ";
660 sdp_type.append(action);
661 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662 EXPECT_NE(std::string::npos, error.find(expected_error));
663 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000664 void SetRemoteDescriptionOfferExpectError(
665 const std::string& expected_error, SessionDescriptionInterface* desc) {
666 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
667 expected_error, desc);
668 }
669 void SetRemoteDescriptionPranswerExpectError(
670 const std::string& expected_error, SessionDescriptionInterface* desc) {
671 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
672 expected_error, desc);
673 }
674 void SetRemoteDescriptionAnswerExpectError(
675 const std::string& expected_error, SessionDescriptionInterface* desc) {
676 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
677 expected_error, desc);
678 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679
680 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
681 SessionDescriptionInterface** nocrypto_answer) {
682 // Create a SDP without Crypto.
683 cricket::MediaSessionOptions options;
684 options.has_video = true;
685 options.bundle_enabled = true;
686 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
687 ASSERT_TRUE(*offer != NULL);
688 VerifyCryptoParams((*offer)->description());
689
690 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
691 cricket::SEC_DISABLED);
692 EXPECT_TRUE(*nocrypto_answer != NULL);
693 }
694
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000695 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
696 SessionDescriptionInterface** nodtls_answer) {
697 cricket::MediaSessionOptions options;
698 options.has_video = true;
699 options.bundle_enabled = true;
700
701 talk_base::scoped_ptr<SessionDescriptionInterface> temp_offer(
702 CreateRemoteOffer(options, cricket::SEC_ENABLED));
703
704 *nodtls_answer =
705 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
706 EXPECT_TRUE(*nodtls_answer != NULL);
707 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
708 VerifyCryptoParams((*nodtls_answer)->description());
709
710 SetFactoryDtlsSrtp();
711 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
712 ASSERT_TRUE(*offer != NULL);
713 VerifyFingerprintStatus((*offer)->description(), true);
714 VerifyCryptoParams((*offer)->description());
715 }
716
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 JsepSessionDescription* CreateRemoteOfferWithVersion(
718 cricket::MediaSessionOptions options,
719 cricket::SecurePolicy secure_policy,
720 const std::string& session_version,
721 const SessionDescriptionInterface* current_desc) {
722 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
723 const cricket::SessionDescription* cricket_desc = NULL;
724 if (current_desc) {
725 cricket_desc = current_desc->description();
726 session_id = current_desc->session_id();
727 }
728
729 desc_factory_->set_secure(secure_policy);
730 JsepSessionDescription* offer(
731 new JsepSessionDescription(JsepSessionDescription::kOffer));
732 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
733 session_id, session_version)) {
734 delete offer;
735 offer = NULL;
736 }
737 return offer;
738 }
739 JsepSessionDescription* CreateRemoteOffer(
740 cricket::MediaSessionOptions options) {
741 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
742 kSessionVersion, NULL);
743 }
744 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000745 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
746 return CreateRemoteOfferWithVersion(
747 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 }
749 JsepSessionDescription* CreateRemoteOffer(
750 cricket::MediaSessionOptions options,
751 const SessionDescriptionInterface* current_desc) {
752 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
753 kSessionVersion, current_desc);
754 }
755
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000756 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
757 const char* sctp_stream_name, int new_port,
758 cricket::MediaSessionOptions options) {
759 options.data_channel_type = cricket::DCT_SCTP;
760 options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel",
761 sctp_stream_name);
762 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
763 }
764
765 // Takes ownership of offer_basis (and deletes it).
766 JsepSessionDescription* ChangeSDPSctpPort(
767 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
768 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
769 // SessionDescription from the mutated string.
770 const char* default_port_str = "5000";
771 char new_port_str[16];
772 talk_base::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
773 std::string offer_str;
774 offer_basis->ToString(&offer_str);
775 talk_base::replace_substrs(default_port_str, strlen(default_port_str),
776 new_port_str, strlen(new_port_str),
777 &offer_str);
778 JsepSessionDescription* offer = new JsepSessionDescription(
779 offer_basis->type());
780 delete offer_basis;
781 offer->Initialize(offer_str, NULL);
782 return offer;
783 }
784
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000785 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
786 // before this function to decide which streams to create.
787 JsepSessionDescription* CreateRemoteOffer() {
788 cricket::MediaSessionOptions options;
789 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
790 return CreateRemoteOffer(options, session_->remote_description());
791 }
792
793 JsepSessionDescription* CreateRemoteAnswer(
794 const SessionDescriptionInterface* offer,
795 cricket::MediaSessionOptions options,
796 cricket::SecurePolicy policy) {
797 desc_factory_->set_secure(policy);
798 const std::string session_id =
799 talk_base::ToString(talk_base::CreateRandomId64());
800 JsepSessionDescription* answer(
801 new JsepSessionDescription(JsepSessionDescription::kAnswer));
802 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
803 options, NULL),
804 session_id, kSessionVersion)) {
805 delete answer;
806 answer = NULL;
807 }
808 return answer;
809 }
810
811 JsepSessionDescription* CreateRemoteAnswer(
812 const SessionDescriptionInterface* offer,
813 cricket::MediaSessionOptions options) {
814 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
815 }
816
817 // Creates an answer session description with streams based on
818 // |mediastream_signaling_|. Call
819 // mediastream_signaling_.UseOptionsWithStreamX() before this function
820 // to decide which streams to create.
821 JsepSessionDescription* CreateRemoteAnswer(
822 const SessionDescriptionInterface* offer) {
823 cricket::MediaSessionOptions options;
824 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
825 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
826 }
827
828 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000829 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000830 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000831 mediastream_signaling_.SendAudioVideoStream1();
832 FakeConstraints constraints;
833 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000834 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
836 // and answer.
837 SetLocalDescriptionWithoutError(offer);
838
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000839 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
840 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000841 std::string sdp;
842 EXPECT_TRUE(answer->ToString(&sdp));
843
844 size_t expected_candidate_num = 2;
845 if (!rtcp_mux) {
846 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
847 // for rtp and rtcp.
848 expected_candidate_num = 4;
849 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000850 const std::string kRtcpMux = "a=rtcp-mux";
851 const std::string kXRtcpMux = "a=xrtcp-mux";
852 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
853 kXRtcpMux.c_str(), kXRtcpMux.length(),
854 &sdp);
855 }
856
857 SessionDescriptionInterface* new_answer = CreateSessionDescription(
858 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859
860 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000861 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
863 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
864 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
865 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
866 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
867 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
868 if (bundle) {
869 EXPECT_TRUE(c0.IsEquivalent(c1));
870 } else {
871 EXPECT_FALSE(c0.IsEquivalent(c1));
872 }
873 }
874 }
875 // Tests that we can only send DTMF when the dtmf codec is supported.
876 void TestCanInsertDtmf(bool can) {
877 if (can) {
878 InitWithDtmfCodec();
879 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000880 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000881 }
882 mediastream_signaling_.SendAudioVideoStream1();
883 CreateAndSetRemoteOfferAndLocalAnswer();
884 EXPECT_FALSE(session_->CanInsertDtmf(""));
885 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
886 }
887
888 // The method sets up a call from the session to itself, in a loopback
889 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000890 // disconnection, and then a permanent disconnection.
891 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892 // by multiple tests with different allocators (e.g. with and without BUNDLE).
893 // While running the call, this method also checks if the session goes through
894 // the correct sequence of ICE states when a connection is established,
895 // broken, and re-established.
896 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000897 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
898 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000899 // The Gathering state should go: New -> Gathering -> Completed.
900 void TestLoopbackCall() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000901 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000902 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000903 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000904 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905
906 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
907 observer_.ice_gathering_state_);
908 SetLocalDescriptionWithoutError(offer);
909 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
910 observer_.ice_connection_state_);
911 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
912 observer_.ice_gathering_state_,
913 kIceCandidatesTimeout);
914 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
915 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
916 observer_.ice_gathering_state_,
917 kIceCandidatesTimeout);
918
919 std::string sdp;
920 offer->ToString(&sdp);
921 SessionDescriptionInterface* desc =
922 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
923 ASSERT_TRUE(desc != NULL);
924 SetRemoteDescriptionWithoutError(desc);
925
926 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
927 observer_.ice_connection_state_,
928 kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +0000929
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000930 // The ice connection state is "Connected" too briefly to catch in a test.
931 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000932 observer_.ice_connection_state_,
933 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934
935 // Adding firewall rule to block ping requests, which should cause
936 // transport channel failure.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000937 fss_->AddRule(false,
938 talk_base::FP_ANY,
939 talk_base::FD_ANY,
940 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
942 observer_.ice_connection_state_,
943 kIceCandidatesTimeout);
944
945 // Clearing the rules, session should move back to completed state.
946 fss_->ClearRules();
947 // Session is automatically calling OnSignalingReady after creation of
948 // new portallocator session which will allocate new set of candidates.
949
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000950 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000951 observer_.ice_connection_state_,
952 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +0000953
954 // Now we block ping requests and wait until the ICE connection transitions
955 // to the Failed state. This will take at least 30 seconds because it must
956 // wait for the Port to timeout.
957 int port_timeout = 30000;
958 fss_->AddRule(false,
959 talk_base::FP_ANY,
960 talk_base::FD_ANY,
961 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
962 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed,
963 observer_.ice_connection_state_,
964 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 }
966
967 void VerifyTransportType(const std::string& content_name,
968 cricket::TransportProtocol protocol) {
969 const cricket::Transport* transport = session_->GetTransport(content_name);
970 ASSERT_TRUE(transport != NULL);
971 EXPECT_EQ(protocol, transport->protocol());
972 }
973
974 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
975 void AddCNCodecs() {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000976 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
977 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
978
979 // Add kCNCodec for dtmf test.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
981 codecs.push_back(kCNCodec1);
982 codecs.push_back(kCNCodec2);
983 media_engine_->SetAudioCodecs(codecs);
984 desc_factory_->set_audio_codecs(codecs);
985 }
986
987 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
988 const cricket::ContentDescription* description = content->description;
989 ASSERT(description != NULL);
990 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000991 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 ASSERT(audio_content_desc != NULL);
993 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
994 if (audio_content_desc->codecs()[i].name == "CN")
995 return false;
996 }
997 return true;
998 }
999
1000 void SetLocalDescriptionWithDataChannel() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001001 webrtc::InternalDataChannelInit dci;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001002 dci.reliable = false;
1003 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001004 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005 SetLocalDescriptionWithoutError(offer);
1006 }
1007
wu@webrtc.org91053e72013-08-10 07:18:04 +00001008 void VerifyMultipleAsyncCreateDescription(
1009 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +00001010 InitWithDtls(!success);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001011 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001012 if (type == CreateSessionDescriptionRequest::kAnswer) {
1013 cricket::MediaSessionOptions options;
1014 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001015 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001016 ASSERT_TRUE(offer.get() != NULL);
1017 SetRemoteDescriptionWithoutError(offer.release());
1018 }
1019
1020 const int kNumber = 3;
1021 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
1022 observers[kNumber];
1023 for (int i = 0; i < kNumber; ++i) {
1024 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
1025 if (type == CreateSessionDescriptionRequest::kOffer) {
1026 session_->CreateOffer(observers[i], NULL);
1027 } else {
1028 session_->CreateAnswer(observers[i], NULL);
1029 }
1030 }
1031
1032 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1033 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1034 WebRtcSessionCreateSDPObserverForTest::kFailed;
1035
1036 for (int i = 0; i < kNumber; ++i) {
1037 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1038 if (success) {
1039 EXPECT_TRUE(observers[i]->description() != NULL);
1040 } else {
1041 EXPECT_TRUE(observers[i]->description() == NULL);
1042 }
1043 }
1044 }
1045
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046 cricket::FakeMediaEngine* media_engine_;
1047 cricket::FakeDataEngine* data_engine_;
1048 cricket::FakeDeviceManager* device_manager_;
1049 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
1050 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001051 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001052 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1053 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
1054 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
1055 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
1056 talk_base::SocketServerScope ss_scope_;
wu@webrtc.org364f2042013-11-20 21:49:41 +00001057 talk_base::SocketAddress stun_socket_addr_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001058 cricket::TestStunServer stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001059 cricket::TestTurnServer turn_server_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 talk_base::FakeNetworkManager network_manager_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001061 talk_base::scoped_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001062 PeerConnectionFactoryInterface::Options options_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001063 talk_base::scoped_ptr<FakeConstraints> constraints_;
1064 FakeMediaStreamSignaling mediastream_signaling_;
1065 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
1066 MockIceObserver observer_;
1067 cricket::FakeVideoMediaChannel* video_channel_;
1068 cricket::FakeVoiceMediaChannel* voice_channel_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001069 PeerConnectionInterface::IceTransportsType ice_type_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001070};
1071
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001072TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
1073 InitWithDtls();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001074 // SDES is disabled when DTLS is on.
1075 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001076}
1077
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001078TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001079 Init(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001080 // SDES is required if DTLS is off.
1081 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001082}
1083
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1085 TestSessionCandidatesWithBundleRtcpMux(false, false);
1086}
1087
1088// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1089// with rtcp-mux and/or bundle.
1090TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1091 TestSessionCandidatesWithBundleRtcpMux(false, true);
1092}
1093
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1095 TestSessionCandidatesWithBundleRtcpMux(true, true);
1096}
1097
1098TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001099 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1100 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001101 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001102 mediastream_signaling_.SendAudioVideoStream1();
1103 InitiateCall();
1104 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1105 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1106 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1107}
1108
1109TEST_F(WebRtcSessionTest, TestStunError) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001110 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1111 AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
1112 fss_->AddRule(false,
1113 talk_base::FP_UDP,
1114 talk_base::FD_ANY,
1115 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001116 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001117 mediastream_signaling_.SendAudioVideoStream1();
1118 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001119 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001120 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1121 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1122 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1123}
1124
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001125TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
1126 Init(NULL);
1127 SessionDescriptionInterface* offer = NULL;
1128 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1129 std::string unknown_action;
1130 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1131 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1132}
1133
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001134// Test creating offers and receive answers and make sure the
1135// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001136TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001137 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001138 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001139 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 const std::string session_id_orig = offer->session_id();
1141 const std::string session_version_orig = offer->session_version();
1142 SetLocalDescriptionWithoutError(offer);
1143
1144 mediastream_signaling_.SendAudioVideoStream2();
1145 SessionDescriptionInterface* answer =
1146 CreateRemoteAnswer(session_->local_description());
1147 SetRemoteDescriptionWithoutError(answer);
1148
1149 video_channel_ = media_engine_->GetVideoChannel(0);
1150 voice_channel_ = media_engine_->GetVoiceChannel(0);
1151
1152 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1153 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1154
1155 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1156 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1157
1158 ASSERT_EQ(1u, video_channel_->send_streams().size());
1159 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1160 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1161 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1162
1163 // Create new offer without send streams.
1164 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001165 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001166
1167 // Verify the session id is the same and the session version is
1168 // increased.
1169 EXPECT_EQ(session_id_orig, offer->session_id());
1170 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1171 talk_base::FromString<uint64>(offer->session_version()));
1172
1173 SetLocalDescriptionWithoutError(offer);
1174
1175 mediastream_signaling_.SendAudioVideoStream2();
1176 answer = CreateRemoteAnswer(session_->local_description());
1177 SetRemoteDescriptionWithoutError(answer);
1178
1179 EXPECT_EQ(0u, video_channel_->send_streams().size());
1180 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1181
1182 // Make sure the receive streams have not changed.
1183 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1184 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1185 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1186 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1187}
1188
1189// Test receiving offers and creating answers and make sure the
1190// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001191TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001192 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001194 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001195 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001196 SetRemoteDescriptionWithoutError(offer);
1197
1198 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001199 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001200 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001201 SetLocalDescriptionWithoutError(answer);
1202
1203 const std::string session_id_orig = answer->session_id();
1204 const std::string session_version_orig = answer->session_version();
1205
1206 video_channel_ = media_engine_->GetVideoChannel(0);
1207 voice_channel_ = media_engine_->GetVoiceChannel(0);
1208
1209 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1210 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1211
1212 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1213 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1214
1215 ASSERT_EQ(1u, video_channel_->send_streams().size());
1216 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1217 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1218 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1219
1220 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001221 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 SetRemoteDescriptionWithoutError(offer);
1223
1224 // Answer by turning off all send streams.
1225 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001226 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227
1228 // Verify the session id is the same and the session version is
1229 // increased.
1230 EXPECT_EQ(session_id_orig, answer->session_id());
1231 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1232 talk_base::FromString<uint64>(answer->session_version()));
1233 SetLocalDescriptionWithoutError(answer);
1234
1235 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1236 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1237 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1238 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1239 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1240 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1241
1242 // Make sure we have no send streams.
1243 EXPECT_EQ(0u, video_channel_->send_streams().size());
1244 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1245}
1246
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001247TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
1248 Init(NULL);
1249 media_engine_->set_fail_create_channel(true);
1250
1251 SessionDescriptionInterface* offer = CreateOffer(NULL);
1252 ASSERT_TRUE(offer != NULL);
1253 // SetRemoteDescription and SetLocalDescription will take the ownership of
1254 // the offer.
1255 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
1256 offer = CreateOffer(NULL);
1257 ASSERT_TRUE(offer != NULL);
1258 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1259}
1260
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001261//
1262// Tests for creating/setting SDP under different SDES/DTLS polices:
1263//
1264// --DTLS off and SDES on
1265// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1266// set local/remote offer/answer with crypto --> success
1267// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1268// failure
1269// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1270// failure
1271// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1272// failure
1273//
1274// --DTLS on and SDES off
1275// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1276// set local/remote offer/answer with DTLS fingerprint --> success
1277// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1278// fingerprint --> failure
1279// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1280// --> failure
1281// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1282// --> failure
1283//
1284// --Encryption disabled: DTLS off and SDES off
1285// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1286// answer without SDES or DTLS --> success
1287// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1288// answer without SDES or DTLS --> success
1289//
1290
1291// Test that we return a failure when applying a remote/local offer that doesn't
1292// have cryptos enabled when DTLS is off.
1293TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001294 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001295 cricket::MediaSessionOptions options;
1296 options.has_video = true;
1297 JsepSessionDescription* offer = CreateRemoteOffer(
1298 options, cricket::SEC_DISABLED);
1299 ASSERT_TRUE(offer != NULL);
1300 VerifyNoCryptoParams(offer->description(), false);
1301 // SetRemoteDescription and SetLocalDescription will take the ownership of
1302 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001303 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1305 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001306 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001307}
1308
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001309// Test that we return a failure when applying a local answer that doesn't have
1310// cryptos enabled when DTLS is off.
1311TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001312 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001313 SessionDescriptionInterface* offer = NULL;
1314 SessionDescriptionInterface* answer = NULL;
1315 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1316 // SetRemoteDescription and SetLocalDescription will take the ownership of
1317 // the offer.
1318 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001319 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320}
1321
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001322// Test we will return fail when apply an remote answer that doesn't have
1323// crypto enabled when DTLS is off.
1324TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001325 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001326 SessionDescriptionInterface* offer = NULL;
1327 SessionDescriptionInterface* answer = NULL;
1328 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1329 // SetRemoteDescription and SetLocalDescription will take the ownership of
1330 // the offer.
1331 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001332 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333}
1334
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001335// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1336// and that we return an answer with a DTLS fingerprint.
1337TEST_F(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001338 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 InitWithDtls();
1341 SetFactoryDtlsSrtp();
1342 cricket::MediaSessionOptions options;
1343 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001344 JsepSessionDescription* offer =
1345 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346 ASSERT_TRUE(offer != NULL);
1347 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001348 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001349
1350 // SetRemoteDescription will take the ownership of the offer.
1351 SetRemoteDescriptionWithoutError(offer);
1352
1353 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001354 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001355 ASSERT_TRUE(answer != NULL);
1356 VerifyFingerprintStatus(answer->description(), true);
1357 // Check that we don't have an a=crypto line in the answer.
1358 VerifyNoCryptoParams(answer->description(), true);
1359
1360 // Now set the local description, which should work, even without a=crypto.
1361 SetLocalDescriptionWithoutError(answer);
1362}
1363
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001364// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1365// and then we accept a remote answer with a DTLS fingerprint successfully.
1366TEST_F(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
1367 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1368 mediastream_signaling_.SendAudioVideoStream1();
1369 InitWithDtls();
1370 SetFactoryDtlsSrtp();
1371
1372 // Verify that we get a crypto fingerprint in the answer.
1373 SessionDescriptionInterface* offer = CreateOffer(NULL);
1374 ASSERT_TRUE(offer != NULL);
1375 VerifyFingerprintStatus(offer->description(), true);
1376 // Check that we don't have an a=crypto line in the offer.
1377 VerifyNoCryptoParams(offer->description(), true);
1378
1379 // Now set the local description, which should work, even without a=crypto.
1380 SetLocalDescriptionWithoutError(offer);
1381
1382 cricket::MediaSessionOptions options;
1383 options.has_video = true;
1384 JsepSessionDescription* answer =
1385 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1386 ASSERT_TRUE(answer != NULL);
1387 VerifyFingerprintStatus(answer->description(), true);
1388 VerifyNoCryptoParams(answer->description(), true);
1389
1390 // SetRemoteDescription will take the ownership of the answer.
1391 SetRemoteDescriptionWithoutError(answer);
1392}
1393
1394// Test that if we support DTLS and the other side didn't offer a fingerprint,
1395// we will fail to set the remote description.
1396TEST_F(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1398 InitWithDtls();
1399 cricket::MediaSessionOptions options;
1400 options.has_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001401 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001402 JsepSessionDescription* offer = CreateRemoteOffer(
1403 options, cricket::SEC_REQUIRED);
1404 ASSERT_TRUE(offer != NULL);
1405 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001406 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001407
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001408 // SetRemoteDescription will take the ownership of the offer.
1409 SetRemoteDescriptionOfferExpectError(
1410 kSdpWithoutDtlsFingerprint, offer);
1411
1412 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1413 // SetLocalDescription will take the ownership of the offer.
1414 SetLocalDescriptionOfferExpectError(
1415 kSdpWithoutDtlsFingerprint, offer);
1416}
1417
1418// Test that we return a failure when applying a local answer that doesn't have
1419// a DTLS fingerprint when DTLS is required.
1420TEST_F(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
1421 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1422 InitWithDtls();
1423 SessionDescriptionInterface* offer = NULL;
1424 SessionDescriptionInterface* answer = NULL;
1425 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1426
1427 // SetRemoteDescription and SetLocalDescription will take the ownership of
1428 // the offer and answer.
1429 SetRemoteDescriptionWithoutError(offer);
1430 SetLocalDescriptionAnswerExpectError(
1431 kSdpWithoutDtlsFingerprint, answer);
1432}
1433
1434// Test that we return a failure when applying a remote answer that doesn't have
1435// a DTLS fingerprint when DTLS is required.
1436TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
1437 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1438 InitWithDtls();
1439 SessionDescriptionInterface* offer = CreateOffer(NULL);
1440 cricket::MediaSessionOptions options;
1441 options.has_video = true;
1442 JsepSessionDescription* answer =
1443 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
1444
1445 // SetRemoteDescription and SetLocalDescription will take the ownership of
1446 // the offer and answer.
1447 SetLocalDescriptionWithoutError(offer);
1448 SetRemoteDescriptionAnswerExpectError(
1449 kSdpWithoutDtlsFingerprint, answer);
1450}
1451
1452// Test that we create a local offer without SDES or DTLS and accept a remote
1453// answer without SDES or DTLS when encryption is disabled.
1454TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
1455 mediastream_signaling_.SendAudioVideoStream1();
1456 options_.disable_encryption = true;
1457 InitWithDtls();
1458
1459 // Verify that we get a crypto fingerprint in the answer.
1460 SessionDescriptionInterface* offer = CreateOffer(NULL);
1461 ASSERT_TRUE(offer != NULL);
1462 VerifyFingerprintStatus(offer->description(), false);
1463 // Check that we don't have an a=crypto line in the offer.
1464 VerifyNoCryptoParams(offer->description(), false);
1465
1466 // Now set the local description, which should work, even without a=crypto.
1467 SetLocalDescriptionWithoutError(offer);
1468
1469 cricket::MediaSessionOptions options;
1470 options.has_video = true;
1471 JsepSessionDescription* answer =
1472 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1473 ASSERT_TRUE(answer != NULL);
1474 VerifyFingerprintStatus(answer->description(), false);
1475 VerifyNoCryptoParams(answer->description(), false);
1476
1477 // SetRemoteDescription will take the ownership of the answer.
1478 SetRemoteDescriptionWithoutError(answer);
1479}
1480
1481// Test that we create a local answer without SDES or DTLS and accept a remote
1482// offer without SDES or DTLS when encryption is disabled.
1483TEST_F(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
1484 options_.disable_encryption = true;
1485 InitWithDtls();
1486
1487 cricket::MediaSessionOptions options;
1488 options.has_video = true;
1489 JsepSessionDescription* offer =
1490 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1491 ASSERT_TRUE(offer != NULL);
1492 VerifyFingerprintStatus(offer->description(), false);
1493 VerifyNoCryptoParams(offer->description(), false);
1494
1495 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496 SetRemoteDescriptionWithoutError(offer);
1497
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001498 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001499 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001500 ASSERT_TRUE(answer != NULL);
1501 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001502 // Check that we don't have an a=crypto line in the answer.
1503 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001505 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 SetLocalDescriptionWithoutError(answer);
1507}
1508
1509TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001510 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511 mediastream_signaling_.SendNothing();
1512 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001513 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514 SetLocalDescriptionWithoutError(offer);
1515
1516 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001517 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 SetLocalDescriptionWithoutError(offer2);
1519}
1520
1521TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001522 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 mediastream_signaling_.SendNothing();
1524 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001525 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 SetRemoteDescriptionWithoutError(offer);
1527
wu@webrtc.org91053e72013-08-10 07:18:04 +00001528 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529 SetRemoteDescriptionWithoutError(offer2);
1530}
1531
1532TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001533 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001535 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001537 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001538 SetRemoteDescriptionOfferExpectError(
1539 "Called in wrong state: STATE_SENTINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540}
1541
1542TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001543 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001545 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001547 offer = CreateOffer(NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001548 SetLocalDescriptionOfferExpectError(
1549 "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550}
1551
1552TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001553 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001554 mediastream_signaling_.SendNothing();
1555 SessionDescriptionInterface* offer = CreateRemoteOffer();
1556 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1557
1558 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001559 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001560 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1561 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1562
1563 mediastream_signaling_.SendAudioVideoStream1();
1564 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001565 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1567
1568 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1569
1570 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001571 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1573}
1574
1575TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001576 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001577 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001578 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1580
1581 JsepSessionDescription* pranswer =
1582 CreateRemoteAnswer(session_->local_description());
1583 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1584
1585 SetRemoteDescriptionExpectState(pranswer,
1586 BaseSession::STATE_RECEIVEDPRACCEPT);
1587
1588 mediastream_signaling_.SendAudioVideoStream1();
1589 JsepSessionDescription* pranswer2 =
1590 CreateRemoteAnswer(session_->local_description());
1591 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1592
1593 SetRemoteDescriptionExpectState(pranswer2,
1594 BaseSession::STATE_RECEIVEDPRACCEPT);
1595
1596 mediastream_signaling_.SendAudioVideoStream2();
1597 SessionDescriptionInterface* answer =
1598 CreateRemoteAnswer(session_->local_description());
1599 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1600}
1601
1602TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001603 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604 mediastream_signaling_.SendNothing();
1605 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001606 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 SessionDescriptionInterface* answer =
1608 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001609 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1610 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611}
1612
1613TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001614 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 mediastream_signaling_.SendNothing();
1616 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001617 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618 SessionDescriptionInterface* answer =
1619 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001620 SetRemoteDescriptionAnswerExpectError(
1621 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622}
1623
1624TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001625 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 mediastream_signaling_.SendAudioVideoStream1();
1627
1628 cricket::Candidate candidate;
1629 candidate.set_component(1);
1630 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1631
1632 // Fail since we have not set a offer description.
1633 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1634
wu@webrtc.org91053e72013-08-10 07:18:04 +00001635 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636 SetLocalDescriptionWithoutError(offer);
1637 // Candidate should be allowed to add before remote description.
1638 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1639 candidate.set_component(2);
1640 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1641 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1642
1643 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1644 session_->local_description());
1645 SetRemoteDescriptionWithoutError(answer);
1646
1647 // Verifying the candidates are copied properly from internal vector.
1648 const SessionDescriptionInterface* remote_desc =
1649 session_->remote_description();
1650 ASSERT_TRUE(remote_desc != NULL);
1651 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1652 const IceCandidateCollection* candidates =
1653 remote_desc->candidates(kMediaContentIndex0);
1654 ASSERT_EQ(2u, candidates->count());
1655 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1656 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1657 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1658 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1659
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001660 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
1661 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662 candidate.set_component(2);
1663 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1664 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001665 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001666
1667 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1668 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1669}
1670
1671// Test that a remote candidate is added to the remote session description and
1672// that it is retained if the remote session description is changed.
1673TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001674 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001675 cricket::Candidate candidate1;
1676 candidate1.set_component(1);
1677 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1678 candidate1);
1679 mediastream_signaling_.SendAudioVideoStream1();
1680 CreateAndSetRemoteOfferAndLocalAnswer();
1681
1682 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1683 const SessionDescriptionInterface* remote_desc =
1684 session_->remote_description();
1685 ASSERT_TRUE(remote_desc != NULL);
1686 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1687 const IceCandidateCollection* candidates =
1688 remote_desc->candidates(kMediaContentIndex0);
1689 ASSERT_EQ(1u, candidates->count());
1690 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1691
1692 // Update the RemoteSessionDescription with a new session description and
1693 // a candidate and check that the new remote session description contains both
1694 // candidates.
1695 SessionDescriptionInterface* offer = CreateRemoteOffer();
1696 cricket::Candidate candidate2;
1697 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1698 candidate2);
1699 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1700 SetRemoteDescriptionWithoutError(offer);
1701
1702 remote_desc = session_->remote_description();
1703 ASSERT_TRUE(remote_desc != NULL);
1704 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1705 candidates = remote_desc->candidates(kMediaContentIndex0);
1706 ASSERT_EQ(2u, candidates->count());
1707 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1708 // Username and password have be updated with the TransportInfo of the
1709 // SessionDescription, won't be equal to the original one.
1710 candidate2.set_username(candidates->at(0)->candidate().username());
1711 candidate2.set_password(candidates->at(0)->candidate().password());
1712 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1713 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1714 // No need to verify the username and password.
1715 candidate1.set_username(candidates->at(1)->candidate().username());
1716 candidate1.set_password(candidates->at(1)->candidate().password());
1717 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1718
1719 // Test that the candidate is ignored if we can add the same candidate again.
1720 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1721}
1722
1723// Test that local candidates are added to the local session description and
1724// that they are retained if the local session description is changed.
1725TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001726 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001727 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001728 mediastream_signaling_.SendAudioVideoStream1();
1729 CreateAndSetRemoteOfferAndLocalAnswer();
1730
1731 const SessionDescriptionInterface* local_desc = session_->local_description();
1732 const IceCandidateCollection* candidates =
1733 local_desc->candidates(kMediaContentIndex0);
1734 ASSERT_TRUE(candidates != NULL);
1735 EXPECT_EQ(0u, candidates->count());
1736
1737 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1738
1739 local_desc = session_->local_description();
1740 candidates = local_desc->candidates(kMediaContentIndex0);
1741 ASSERT_TRUE(candidates != NULL);
1742 EXPECT_LT(0u, candidates->count());
1743 candidates = local_desc->candidates(1);
1744 ASSERT_TRUE(candidates != NULL);
1745 EXPECT_LT(0u, candidates->count());
1746
1747 // Update the session descriptions.
1748 mediastream_signaling_.SendAudioVideoStream1();
1749 CreateAndSetRemoteOfferAndLocalAnswer();
1750
1751 local_desc = session_->local_description();
1752 candidates = local_desc->candidates(kMediaContentIndex0);
1753 ASSERT_TRUE(candidates != NULL);
1754 EXPECT_LT(0u, candidates->count());
1755 candidates = local_desc->candidates(1);
1756 ASSERT_TRUE(candidates != NULL);
1757 EXPECT_LT(0u, candidates->count());
1758}
1759
1760// Test that we can set a remote session description with remote candidates.
1761TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001762 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763
1764 cricket::Candidate candidate1;
1765 candidate1.set_component(1);
1766 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1767 candidate1);
1768 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001769 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001770
1771 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1772 SetRemoteDescriptionWithoutError(offer);
1773
1774 const SessionDescriptionInterface* remote_desc =
1775 session_->remote_description();
1776 ASSERT_TRUE(remote_desc != NULL);
1777 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1778 const IceCandidateCollection* candidates =
1779 remote_desc->candidates(kMediaContentIndex0);
1780 ASSERT_EQ(1u, candidates->count());
1781 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1782
wu@webrtc.org91053e72013-08-10 07:18:04 +00001783 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784 SetLocalDescriptionWithoutError(answer);
1785}
1786
1787// Test that offers and answers contains ice candidates when Ice candidates have
1788// been gathered.
1789TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001790 AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001791 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 mediastream_signaling_.SendAudioVideoStream1();
1793 // Ice is started but candidates are not provided until SetLocalDescription
1794 // is called.
1795 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1796 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1797 CreateAndSetRemoteOfferAndLocalAnswer();
1798 // Wait until at least one local candidate has been collected.
1799 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1800 kIceCandidatesTimeout);
1801 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1802 kIceCandidatesTimeout);
1803
1804 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001805 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001806 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1807 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1808 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1809 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1810
1811 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1812 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001813 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1815 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1816 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1817 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1818 SetLocalDescriptionWithoutError(answer);
1819}
1820
1821// Verifies TransportProxy and media channels are created with content names
1822// present in the SessionDescription.
1823TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001824 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825 mediastream_signaling_.SendAudioVideoStream1();
1826 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001827 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001828
1829 // CreateOffer creates session description with the content names "audio" and
1830 // "video". Goal is to modify these content names and verify transport channel
1831 // proxy in the BaseSession, as proxies are created with the content names
1832 // present in SDP.
1833 std::string sdp;
1834 EXPECT_TRUE(offer->ToString(&sdp));
1835 const std::string kAudioMid = "a=mid:audio";
1836 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1837 const std::string kVideoMid = "a=mid:video";
1838 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1839
1840 // Replacing |audio| with |audio_content_name|.
1841 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1842 kAudioMidReplaceStr.c_str(),
1843 kAudioMidReplaceStr.length(),
1844 &sdp);
1845 // Replacing |video| with |video_content_name|.
1846 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1847 kVideoMidReplaceStr.c_str(),
1848 kVideoMidReplaceStr.length(),
1849 &sdp);
1850
1851 SessionDescriptionInterface* modified_offer =
1852 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1853
1854 SetRemoteDescriptionWithoutError(modified_offer);
1855
1856 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001857 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858 SetLocalDescriptionWithoutError(answer);
1859
1860 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1861 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1862 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1863 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1864}
1865
1866// Test that an offer contains the correct media content descriptions based on
1867// the send streams when no constraints have been set.
1868TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001869 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001871 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872 ASSERT_TRUE(offer != NULL);
1873 const cricket::ContentInfo* content =
1874 cricket::GetFirstAudioContent(offer->description());
1875 EXPECT_TRUE(content != NULL);
1876 content = cricket::GetFirstVideoContent(offer->description());
1877 EXPECT_TRUE(content == NULL);
1878}
1879
1880// Test that an offer contains the correct media content descriptions based on
1881// the send streams when no constraints have been set.
1882TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001883 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001884 // Test Audio only offer.
1885 mediastream_signaling_.UseOptionsAudioOnly();
1886 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001887 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001888 const cricket::ContentInfo* content =
1889 cricket::GetFirstAudioContent(offer->description());
1890 EXPECT_TRUE(content != NULL);
1891 content = cricket::GetFirstVideoContent(offer->description());
1892 EXPECT_TRUE(content == NULL);
1893
1894 // Test Audio / Video offer.
1895 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001896 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001897 content = cricket::GetFirstAudioContent(offer->description());
1898 EXPECT_TRUE(content != NULL);
1899 content = cricket::GetFirstVideoContent(offer->description());
1900 EXPECT_TRUE(content != NULL);
1901}
1902
1903// Test that an offer contains no media content descriptions if
1904// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1905TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001906 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907 webrtc::FakeConstraints constraints_no_receive;
1908 constraints_no_receive.SetMandatoryReceiveAudio(false);
1909 constraints_no_receive.SetMandatoryReceiveVideo(false);
1910
1911 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001912 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001913 ASSERT_TRUE(offer != NULL);
1914 const cricket::ContentInfo* content =
1915 cricket::GetFirstAudioContent(offer->description());
1916 EXPECT_TRUE(content == NULL);
1917 content = cricket::GetFirstVideoContent(offer->description());
1918 EXPECT_TRUE(content == NULL);
1919}
1920
1921// Test that an offer contains only audio media content descriptions if
1922// kOfferToReceiveAudio constraints are set to true.
1923TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001924 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001925 webrtc::FakeConstraints constraints_audio_only;
1926 constraints_audio_only.SetMandatoryReceiveAudio(true);
1927 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001928 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001929
1930 const cricket::ContentInfo* content =
1931 cricket::GetFirstAudioContent(offer->description());
1932 EXPECT_TRUE(content != NULL);
1933 content = cricket::GetFirstVideoContent(offer->description());
1934 EXPECT_TRUE(content == NULL);
1935}
1936
1937// Test that an offer contains audio and video media content descriptions if
1938// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1939TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001940 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001941 // Test Audio / Video offer.
1942 webrtc::FakeConstraints constraints_audio_video;
1943 constraints_audio_video.SetMandatoryReceiveAudio(true);
1944 constraints_audio_video.SetMandatoryReceiveVideo(true);
1945 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001946 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001947 const cricket::ContentInfo* content =
1948 cricket::GetFirstAudioContent(offer->description());
1949
1950 EXPECT_TRUE(content != NULL);
1951 content = cricket::GetFirstVideoContent(offer->description());
1952 EXPECT_TRUE(content != NULL);
1953
1954 // TODO(perkj): Should the direction be set to SEND_ONLY if
1955 // The constraints is set to not receive audio or video but a track is added?
1956}
1957
1958// Test that an answer can not be created if the last remote description is not
1959// an offer.
1960TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001961 Init(NULL);
1962 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963 SetLocalDescriptionWithoutError(offer);
1964 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1965 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001966 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967}
1968
1969// Test that an answer contains the correct media content descriptions when no
1970// constraints have been set.
1971TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001972 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973 // Create a remote offer with audio and video content.
1974 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1975 SetRemoteDescriptionWithoutError(offer.release());
1976 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001977 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001978 const cricket::ContentInfo* content =
1979 cricket::GetFirstAudioContent(answer->description());
1980 ASSERT_TRUE(content != NULL);
1981 EXPECT_FALSE(content->rejected);
1982
1983 content = cricket::GetFirstVideoContent(answer->description());
1984 ASSERT_TRUE(content != NULL);
1985 EXPECT_FALSE(content->rejected);
1986}
1987
1988// Test that an answer contains the correct media content descriptions when no
1989// constraints have been set and the offer only contain audio.
1990TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001991 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001992 // Create a remote offer with audio only.
1993 cricket::MediaSessionOptions options;
1994 options.has_audio = true;
1995 options.has_video = false;
1996 talk_base::scoped_ptr<JsepSessionDescription> offer(
1997 CreateRemoteOffer(options));
1998 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1999 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
2000
2001 SetRemoteDescriptionWithoutError(offer.release());
2002 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002003 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 const cricket::ContentInfo* content =
2005 cricket::GetFirstAudioContent(answer->description());
2006 ASSERT_TRUE(content != NULL);
2007 EXPECT_FALSE(content->rejected);
2008
2009 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
2010}
2011
2012// Test that an answer contains the correct media content descriptions when no
2013// constraints have been set.
2014TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002015 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 // Create a remote offer with audio and video content.
2017 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2018 SetRemoteDescriptionWithoutError(offer.release());
2019 // Test with a stream with tracks.
2020 mediastream_signaling_.SendAudioVideoStream1();
2021 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002022 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023 const cricket::ContentInfo* content =
2024 cricket::GetFirstAudioContent(answer->description());
2025 ASSERT_TRUE(content != NULL);
2026 EXPECT_FALSE(content->rejected);
2027
2028 content = cricket::GetFirstVideoContent(answer->description());
2029 ASSERT_TRUE(content != NULL);
2030 EXPECT_FALSE(content->rejected);
2031}
2032
2033// Test that an answer contains the correct media content descriptions when
2034// constraints have been set but no stream is sent.
2035TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002036 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002037 // Create a remote offer with audio and video content.
2038 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2039 SetRemoteDescriptionWithoutError(offer.release());
2040
2041 webrtc::FakeConstraints constraints_no_receive;
2042 constraints_no_receive.SetMandatoryReceiveAudio(false);
2043 constraints_no_receive.SetMandatoryReceiveVideo(false);
2044
2045 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002046 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002047 const cricket::ContentInfo* content =
2048 cricket::GetFirstAudioContent(answer->description());
2049 ASSERT_TRUE(content != NULL);
2050 EXPECT_TRUE(content->rejected);
2051
2052 content = cricket::GetFirstVideoContent(answer->description());
2053 ASSERT_TRUE(content != NULL);
2054 EXPECT_TRUE(content->rejected);
2055}
2056
2057// Test that an answer contains the correct media content descriptions when
2058// constraints have been set and streams are sent.
2059TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002060 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061 // Create a remote offer with audio and video content.
2062 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2063 SetRemoteDescriptionWithoutError(offer.release());
2064
2065 webrtc::FakeConstraints constraints_no_receive;
2066 constraints_no_receive.SetMandatoryReceiveAudio(false);
2067 constraints_no_receive.SetMandatoryReceiveVideo(false);
2068
2069 // Test with a stream with tracks.
2070 mediastream_signaling_.SendAudioVideoStream1();
2071 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002072 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002073
2074 // TODO(perkj): Should the direction be set to SEND_ONLY?
2075 const cricket::ContentInfo* content =
2076 cricket::GetFirstAudioContent(answer->description());
2077 ASSERT_TRUE(content != NULL);
2078 EXPECT_FALSE(content->rejected);
2079
2080 // TODO(perkj): Should the direction be set to SEND_ONLY?
2081 content = cricket::GetFirstVideoContent(answer->description());
2082 ASSERT_TRUE(content != NULL);
2083 EXPECT_FALSE(content->rejected);
2084}
2085
2086TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2087 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002088 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 webrtc::FakeConstraints constraints;
2090 constraints.SetOptionalVAD(false);
2091 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002092 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093 const cricket::ContentInfo* content =
2094 cricket::GetFirstAudioContent(offer->description());
2095 EXPECT_TRUE(content != NULL);
2096 EXPECT_TRUE(VerifyNoCNCodecs(content));
2097}
2098
2099TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2100 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002101 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002102 // Create a remote offer with audio and video content.
2103 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
2104 SetRemoteDescriptionWithoutError(offer.release());
2105
2106 webrtc::FakeConstraints constraints;
2107 constraints.SetOptionalVAD(false);
2108 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002109 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002110 const cricket::ContentInfo* content =
2111 cricket::GetFirstAudioContent(answer->description());
2112 ASSERT_TRUE(content != NULL);
2113 EXPECT_TRUE(VerifyNoCNCodecs(content));
2114}
2115
2116// This test verifies the call setup when remote answer with audio only and
2117// later updates with video.
2118TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002119 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002120 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2121 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2122
2123 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002124 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002125
2126 cricket::MediaSessionOptions options;
2127 options.has_video = false;
2128 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2129
2130 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2131 // and answer;
2132 SetLocalDescriptionWithoutError(offer);
2133 SetRemoteDescriptionWithoutError(answer);
2134
2135 video_channel_ = media_engine_->GetVideoChannel(0);
2136 voice_channel_ = media_engine_->GetVoiceChannel(0);
2137
2138 ASSERT_TRUE(video_channel_ == NULL);
2139
2140 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2141 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2142 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2143
2144 // Let the remote end update the session descriptions, with Audio and Video.
2145 mediastream_signaling_.SendAudioVideoStream2();
2146 CreateAndSetRemoteOfferAndLocalAnswer();
2147
2148 video_channel_ = media_engine_->GetVideoChannel(0);
2149 voice_channel_ = media_engine_->GetVoiceChannel(0);
2150
2151 ASSERT_TRUE(video_channel_ != NULL);
2152 ASSERT_TRUE(voice_channel_ != NULL);
2153
2154 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2155 ASSERT_EQ(1u, video_channel_->send_streams().size());
2156 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2157 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2158 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2159 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2160 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2161 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2162
2163 // Change session back to audio only.
2164 mediastream_signaling_.UseOptionsAudioOnly();
2165 CreateAndSetRemoteOfferAndLocalAnswer();
2166
2167 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2168 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2169 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2170 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2171 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2172}
2173
2174// This test verifies the call setup when remote answer with video only and
2175// later updates with audio.
2176TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002177 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002178 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2179 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2180 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002181 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002182
2183 cricket::MediaSessionOptions options;
2184 options.has_audio = false;
2185 options.has_video = true;
2186 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2187 offer, options, cricket::SEC_ENABLED);
2188
2189 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2190 // and answer.
2191 SetLocalDescriptionWithoutError(offer);
2192 SetRemoteDescriptionWithoutError(answer);
2193
2194 video_channel_ = media_engine_->GetVideoChannel(0);
2195 voice_channel_ = media_engine_->GetVoiceChannel(0);
2196
2197 ASSERT_TRUE(voice_channel_ == NULL);
2198 ASSERT_TRUE(video_channel_ != NULL);
2199
2200 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2201 ASSERT_EQ(1u, video_channel_->send_streams().size());
2202 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2203
2204 // Update the session descriptions, with Audio and Video.
2205 mediastream_signaling_.SendAudioVideoStream2();
2206 CreateAndSetRemoteOfferAndLocalAnswer();
2207
2208 voice_channel_ = media_engine_->GetVoiceChannel(0);
2209 ASSERT_TRUE(voice_channel_ != NULL);
2210
2211 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2212 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2213 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2214 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2215
2216 // Change session back to video only.
2217 mediastream_signaling_.UseOptionsVideoOnly();
2218 CreateAndSetRemoteOfferAndLocalAnswer();
2219
2220 video_channel_ = media_engine_->GetVideoChannel(0);
2221 voice_channel_ = media_engine_->GetVoiceChannel(0);
2222
2223 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2224 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2225 ASSERT_EQ(1u, video_channel_->send_streams().size());
2226 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2227}
2228
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002229TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002230 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002231 mediastream_signaling_.SendAudioVideoStream1();
2232 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002233 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002234 VerifyCryptoParams(offer->description());
2235 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002236 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 VerifyCryptoParams(answer->description());
2238}
2239
2240TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002241 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002242 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002243 mediastream_signaling_.SendAudioVideoStream1();
2244 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002245 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002246 VerifyNoCryptoParams(offer->description(), false);
2247}
2248
2249TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002250 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002251 VerifyAnswerFromNonCryptoOffer();
2252}
2253
2254TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002255 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002256 VerifyAnswerFromCryptoOffer();
2257}
2258
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002259// This test verifies that setLocalDescription fails if
2260// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2261TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
2262 Init(NULL);
2263 mediastream_signaling_.SendAudioVideoStream1();
2264 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2265 std::string sdp;
2266 RemoveIceUfragPwdLines(offer.get(), &sdp);
2267 SessionDescriptionInterface* modified_offer =
2268 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002269 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002270}
2271
2272// This test verifies that setRemoteDescription fails if
2273// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2274TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
2275 Init(NULL);
2276 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2277 std::string sdp;
2278 RemoveIceUfragPwdLines(offer.get(), &sdp);
2279 SessionDescriptionInterface* modified_offer =
2280 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002281 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002282}
2283
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002284// This test verifies that setLocalDescription fails if local offer has
2285// too short ice ufrag and pwd strings.
2286TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) {
2287 Init(NULL);
2288 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
2289 mediastream_signaling_.SendAudioVideoStream1();
2290 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2291 std::string sdp;
2292 // Modifying ice ufrag and pwd in local offer with strings smaller than the
2293 // recommended values of 4 and 22 bytes respectively.
2294 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2295 SessionDescriptionInterface* modified_offer =
2296 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2297 std::string error;
2298 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2299
2300 // Test with string greater than 256.
2301 sdp.clear();
2302 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2303 &sdp);
2304 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2305 NULL);
2306 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2307}
2308
2309// This test verifies that setRemoteDescription fails if remote offer has
2310// too short ice ufrag and pwd strings.
2311TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) {
2312 Init(NULL);
2313 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
2314 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2315 std::string sdp;
2316 // Modifying ice ufrag and pwd in remote offer with strings smaller than the
2317 // recommended values of 4 and 22 bytes respectively.
2318 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2319 SessionDescriptionInterface* modified_offer =
2320 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2321 std::string error;
2322 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2323
2324 sdp.clear();
2325 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2326 &sdp);
2327 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2328 NULL);
2329 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2330}
2331
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
2333 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
2334 // local description is removed by the application, BUNDLE flag should be
2335 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00002336 Init(NULL);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002337 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2338 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002339 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002340 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002341 cricket::SessionDescription* offer_copy =
2342 offer->description()->Copy();
2343 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2344 JsepSessionDescription* modified_offer =
2345 new JsepSessionDescription(JsepSessionDescription::kOffer);
2346 modified_offer->Initialize(offer_copy, "1", "1");
2347
2348 SetLocalDescriptionWithoutError(modified_offer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002349 EXPECT_FALSE(allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350}
2351
2352TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002353 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002354 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002355 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2356 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002357 FakeConstraints constraints;
2358 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002359 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002360 SetLocalDescriptionWithoutError(offer);
2361 mediastream_signaling_.SendAudioVideoStream2();
2362 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2363 CreateRemoteAnswer(session_->local_description()));
2364 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2365 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2366 JsepSessionDescription* modified_answer =
2367 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2368 modified_answer->Initialize(answer_copy, "1", "1");
2369 SetRemoteDescriptionWithoutError(modified_answer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002370 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2371 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372
2373 video_channel_ = media_engine_->GetVideoChannel(0);
2374 voice_channel_ = media_engine_->GetVoiceChannel(0);
2375
2376 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2377 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
2378
2379 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2380 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
2381
2382 ASSERT_EQ(1u, video_channel_->send_streams().size());
2383 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
2384 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2385 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
2386}
2387
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002388// This test verifies that SetLocalDescription and SetRemoteDescription fails
2389// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2390TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002391 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002392 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002393 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2394 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002395 FakeConstraints constraints;
2396 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002397 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002398 std::string offer_str;
2399 offer->ToString(&offer_str);
2400 // Disable rtcp-mux
2401 const std::string rtcp_mux = "rtcp-mux";
2402 const std::string xrtcp_mux = "xrtcp-mux";
2403 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
2404 xrtcp_mux.c_str(), xrtcp_mux.length(),
2405 &offer_str);
2406 JsepSessionDescription *local_offer =
2407 new JsepSessionDescription(JsepSessionDescription::kOffer);
2408 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002409 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002410 JsepSessionDescription *remote_offer =
2411 new JsepSessionDescription(JsepSessionDescription::kOffer);
2412 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002413 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002414 // Trying unmodified SDP.
2415 SetLocalDescriptionWithoutError(offer);
2416}
2417
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002418TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002419 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002420 mediastream_signaling_.SendAudioVideoStream1();
2421 CreateAndSetRemoteOfferAndLocalAnswer();
2422 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2423 ASSERT_TRUE(channel != NULL);
2424 ASSERT_EQ(1u, channel->recv_streams().size());
2425 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2426 double left_vol, right_vol;
2427 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2428 EXPECT_EQ(1, left_vol);
2429 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002430 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2431 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002432 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2433 EXPECT_EQ(0, left_vol);
2434 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002435 EXPECT_EQ(0, renderer->channel_id());
2436 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002437 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2438 EXPECT_EQ(1, left_vol);
2439 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002440 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002441}
2442
2443TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002444 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002445 mediastream_signaling_.SendAudioVideoStream1();
2446 CreateAndSetRemoteOfferAndLocalAnswer();
2447 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2448 ASSERT_TRUE(channel != NULL);
2449 ASSERT_EQ(1u, channel->send_streams().size());
2450 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2451 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2452
2453 cricket::AudioOptions options;
2454 options.echo_cancellation.Set(true);
2455
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002456 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2457 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002458 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2459 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002460 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002461 EXPECT_TRUE(renderer->sink() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002462
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002463 // This will trigger SetSink(NULL) to the |renderer|.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002464 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002465 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2466 bool value;
2467 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2468 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002469 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002470 EXPECT_TRUE(renderer->sink() == NULL);
2471}
2472
2473TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) {
2474 Init(NULL);
2475 mediastream_signaling_.SendAudioVideoStream1();
2476 CreateAndSetRemoteOfferAndLocalAnswer();
2477 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2478 ASSERT_TRUE(channel != NULL);
2479 ASSERT_EQ(1u, channel->send_streams().size());
2480 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2481
2482 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2483 cricket::AudioOptions options;
2484 session_->SetAudioSend(send_ssrc, true, options, renderer.get());
2485 EXPECT_TRUE(renderer->sink() != NULL);
2486
2487 // Delete the |renderer| and it will trigger OnClose() to the sink, and this
2488 // will invalidate the |renderer_| pointer in the sink and prevent getting a
2489 // SetSink(NULL) callback afterwards.
2490 renderer.reset();
2491
2492 // This will trigger SetSink(NULL) if no OnClose() callback.
2493 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002494}
2495
2496TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002497 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002498 mediastream_signaling_.SendAudioVideoStream1();
2499 CreateAndSetRemoteOfferAndLocalAnswer();
2500 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2501 ASSERT_TRUE(channel != NULL);
2502 ASSERT_LT(0u, channel->renderers().size());
2503 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2504 ASSERT_EQ(1u, channel->recv_streams().size());
2505 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2506 cricket::FakeVideoRenderer renderer;
2507 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2508 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2509 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2510 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2511}
2512
2513TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002514 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002515 mediastream_signaling_.SendAudioVideoStream1();
2516 CreateAndSetRemoteOfferAndLocalAnswer();
2517 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2518 ASSERT_TRUE(channel != NULL);
2519 ASSERT_EQ(1u, channel->send_streams().size());
2520 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2521 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2522 cricket::VideoOptions* options = NULL;
2523 session_->SetVideoSend(send_ssrc, false, options);
2524 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2525 session_->SetVideoSend(send_ssrc, true, options);
2526 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2527}
2528
2529TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2530 TestCanInsertDtmf(false);
2531}
2532
2533TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2534 TestCanInsertDtmf(true);
2535}
2536
2537TEST_F(WebRtcSessionTest, InsertDtmf) {
2538 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002539 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002540 mediastream_signaling_.SendAudioVideoStream1();
2541 CreateAndSetRemoteOfferAndLocalAnswer();
2542 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2543 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2544
2545 // Insert DTMF
2546 const int expected_flags = DF_SEND;
2547 const int expected_duration = 90;
2548 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2549 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2550 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2551
2552 // Verify
2553 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2554 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2555 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2556 expected_duration, expected_flags));
2557 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2558 expected_duration, expected_flags));
2559 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2560 expected_duration, expected_flags));
2561}
2562
2563// This test verifies the |initiator| flag when session initiates the call.
2564TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002565 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002566 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002567 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002568 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2569 SetLocalDescriptionWithoutError(offer);
2570 EXPECT_TRUE(session_->initiator());
2571 SetRemoteDescriptionWithoutError(answer);
2572 EXPECT_TRUE(session_->initiator());
2573}
2574
2575// This test verifies the |initiator| flag when session receives the call.
2576TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002577 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002578 EXPECT_FALSE(session_->initiator());
2579 SessionDescriptionInterface* offer = CreateRemoteOffer();
2580 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002581 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002582
2583 EXPECT_FALSE(session_->initiator());
2584 SetLocalDescriptionWithoutError(answer);
2585 EXPECT_FALSE(session_->initiator());
2586}
2587
2588// This test verifies the ice protocol type at initiator of the call
2589// if |a=ice-options:google-ice| is present in answer.
2590TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002591 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002592 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002593 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002594 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002595 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002596 SetLocalDescriptionWithoutError(offer);
2597 std::string sdp;
2598 EXPECT_TRUE(answer->ToString(&sdp));
2599 // Adding ice-options to the session level.
2600 InjectAfter("t=0 0\r\n",
2601 "a=ice-options:google-ice\r\n",
2602 &sdp);
2603 SessionDescriptionInterface* answer_with_gice =
2604 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2605 SetRemoteDescriptionWithoutError(answer_with_gice);
2606 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2607 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2608}
2609
2610// This test verifies the ice protocol type at initiator of the call
2611// if ICE RFC5245 is supported in answer.
2612TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002613 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002614 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002615 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002616 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2617 SetLocalDescriptionWithoutError(offer);
2618
2619 SetRemoteDescriptionWithoutError(answer);
2620 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2621 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2622}
2623
2624// This test verifies the ice protocol type at receiver side of the call if
2625// receiver decides to use google-ice.
2626TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002627 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002628 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002629 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002630 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002631 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002632 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002633 std::string sdp;
2634 EXPECT_TRUE(answer->ToString(&sdp));
2635 // Adding ice-options to the session level.
2636 InjectAfter("t=0 0\r\n",
2637 "a=ice-options:google-ice\r\n",
2638 &sdp);
2639 SessionDescriptionInterface* answer_with_gice =
2640 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2641 SetLocalDescriptionWithoutError(answer_with_gice);
2642 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2643 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2644}
2645
2646// This test verifies the ice protocol type at receiver side of the call if
2647// receiver decides to use ice RFC 5245.
2648TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002649 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002650 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002651 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002652 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002653 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002654 SetLocalDescriptionWithoutError(answer);
2655 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2656 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2657}
2658
2659// This test verifies the session state when ICE RFC5245 in offer and
2660// ICE google-ice in answer.
2661TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002662 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002663 mediastream_signaling_.SendAudioVideoStream1();
2664 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002665 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002666 std::string offer_str;
2667 offer->ToString(&offer_str);
2668 // Disable google-ice
2669 const std::string gice_option = "google-ice";
2670 const std::string xgoogle_xice = "xgoogle-xice";
2671 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2672 xgoogle_xice.c_str(), xgoogle_xice.length(),
2673 &offer_str);
2674 JsepSessionDescription *ice_only_offer =
2675 new JsepSessionDescription(JsepSessionDescription::kOffer);
2676 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2677 SetLocalDescriptionWithoutError(ice_only_offer);
2678 std::string original_offer_sdp;
2679 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002680 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002681 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002682 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002683 SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
2684 pranswer_with_gice);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002685 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002686 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002687 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002688 SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
2689 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002690}
2691
2692// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2693TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002694 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002695 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002696 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002697 SetLocalDescriptionWithoutError(offer);
2698 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2699 CreateRemoteAnswer(session_->local_description()));
2700
2701 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2702 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002703 JsepSessionDescription* modified_answer =
2704 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002705
2706 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2707 answer->session_id(),
2708 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002709 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002710
wu@webrtc.org4e393072014-04-07 17:04:35 +00002711 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002712 std::string sdp;
2713 EXPECT_TRUE(answer->ToString(&sdp));
2714 const std::string kAudioMid = "a=mid:audio";
2715 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002716 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2717 kAudioMidReplaceStr.c_str(),
2718 kAudioMidReplaceStr.length(),
2719 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002720 SessionDescriptionInterface* modified_answer1 =
2721 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002722 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002723
wu@webrtc.org4e393072014-04-07 17:04:35 +00002724 // Different media types.
2725 EXPECT_TRUE(answer->ToString(&sdp));
2726 const std::string kAudioMline = "m=audio";
2727 const std::string kAudioMlineReplaceStr = "m=video";
2728 talk_base::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
2729 kAudioMlineReplaceStr.c_str(),
2730 kAudioMlineReplaceStr.length(),
2731 &sdp);
2732 SessionDescriptionInterface* modified_answer2 =
2733 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2734 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
2735
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002736 SetRemoteDescriptionWithoutError(answer.release());
2737}
2738
2739// Verifying remote offer and local answer have matching m-lines as per
2740// RFC 3264.
2741TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002742 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002743 mediastream_signaling_.SendAudioVideoStream1();
2744 SessionDescriptionInterface* offer = CreateRemoteOffer();
2745 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002746 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002747
2748 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2749 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002750 JsepSessionDescription* modified_answer =
2751 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002752
2753 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2754 answer->session_id(),
2755 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002756 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002757 SetLocalDescriptionWithoutError(answer);
2758}
2759
2760// This test verifies that WebRtcSession does not start candidate allocation
2761// before SetLocalDescription is called.
2762TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002763 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002764 mediastream_signaling_.SendAudioVideoStream1();
2765 SessionDescriptionInterface* offer = CreateRemoteOffer();
2766 cricket::Candidate candidate;
2767 candidate.set_component(1);
2768 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2769 candidate);
2770 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2771 cricket::Candidate candidate1;
2772 candidate1.set_component(1);
2773 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2774 candidate1);
2775 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2776 SetRemoteDescriptionWithoutError(offer);
2777 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2778 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2779
2780 // Pump for 1 second and verify that no candidates are generated.
2781 talk_base::Thread::Current()->ProcessMessages(1000);
2782 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2783 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2784
wu@webrtc.org91053e72013-08-10 07:18:04 +00002785 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002786 SetLocalDescriptionWithoutError(answer);
2787 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2788 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2789 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2790}
2791
2792// This test verifies that crypto parameter is updated in local session
2793// description as per security policy set in MediaSessionDescriptionFactory.
2794TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002795 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002796 mediastream_signaling_.SendAudioVideoStream1();
2797 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002798 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002799
2800 // Making sure SetLocalDescription correctly sets crypto value in
2801 // SessionDescription object after de-serialization of sdp string. The value
2802 // will be set as per MediaSessionDescriptionFactory.
2803 std::string offer_str;
2804 offer->ToString(&offer_str);
2805 SessionDescriptionInterface* jsep_offer_str =
2806 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2807 SetLocalDescriptionWithoutError(jsep_offer_str);
2808 EXPECT_TRUE(session_->voice_channel()->secure_required());
2809 EXPECT_TRUE(session_->video_channel()->secure_required());
2810}
2811
2812// This test verifies the crypto parameter when security is disabled.
2813TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002814 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002815 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002816 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002817 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002818 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002819
2820 // Making sure SetLocalDescription correctly sets crypto value in
2821 // SessionDescription object after de-serialization of sdp string. The value
2822 // will be set as per MediaSessionDescriptionFactory.
2823 std::string offer_str;
2824 offer->ToString(&offer_str);
2825 SessionDescriptionInterface *jsep_offer_str =
2826 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2827 SetLocalDescriptionWithoutError(jsep_offer_str);
2828 EXPECT_FALSE(session_->voice_channel()->secure_required());
2829 EXPECT_FALSE(session_->video_channel()->secure_required());
2830}
2831
2832// This test verifies that an answer contains new ufrag and password if an offer
2833// with new ufrag and password is received.
2834TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002835 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002836 cricket::MediaSessionOptions options;
2837 options.has_audio = true;
2838 options.has_video = true;
2839 talk_base::scoped_ptr<JsepSessionDescription> offer(
2840 CreateRemoteOffer(options));
2841 SetRemoteDescriptionWithoutError(offer.release());
2842
2843 mediastream_signaling_.SendAudioVideoStream1();
2844 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002845 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002846 SetLocalDescriptionWithoutError(answer.release());
2847
2848 // Receive an offer with new ufrag and password.
2849 options.transport_options.ice_restart = true;
2850 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002851 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002852 SetRemoteDescriptionWithoutError(updated_offer1.release());
2853
2854 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002855 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002856
2857 CompareIceUfragAndPassword(updated_answer1->description(),
2858 session_->local_description()->description(),
2859 false);
2860
2861 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002862}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002863
wu@webrtc.org91053e72013-08-10 07:18:04 +00002864// This test verifies that an answer contains old ufrag and password if an offer
2865// with old ufrag and password is received.
2866TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2867 Init(NULL);
2868 cricket::MediaSessionOptions options;
2869 options.has_audio = true;
2870 options.has_video = true;
2871 talk_base::scoped_ptr<JsepSessionDescription> offer(
2872 CreateRemoteOffer(options));
2873 SetRemoteDescriptionWithoutError(offer.release());
2874
2875 mediastream_signaling_.SendAudioVideoStream1();
2876 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2877 CreateAnswer(NULL));
2878 SetLocalDescriptionWithoutError(answer.release());
2879
2880 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002881 options.transport_options.ice_restart = false;
2882 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002883 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002884 SetRemoteDescriptionWithoutError(updated_offer2.release());
2885
2886 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002887 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002888
2889 CompareIceUfragAndPassword(updated_answer2->description(),
2890 session_->local_description()->description(),
2891 true);
2892
2893 SetLocalDescriptionWithoutError(updated_answer2.release());
2894}
2895
2896TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002897 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002898 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002899 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002900 const std::string session_id_orig = offer->session_id();
2901 const std::string session_version_orig = offer->session_version();
2902 SetLocalDescriptionWithoutError(offer);
2903
2904 video_channel_ = media_engine_->GetVideoChannel(0);
2905 video_channel_->set_fail_set_send_codecs(true);
2906
2907 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002908 SessionDescriptionInterface* answer =
2909 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002910 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002911}
2912
2913// Runs the loopback call test with BUNDLE and STUN disabled.
2914TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2915 // Lets try with only UDP ports.
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002916 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002917 cricket::PORTALLOCATOR_DISABLE_TCP |
2918 cricket::PORTALLOCATOR_DISABLE_STUN |
2919 cricket::PORTALLOCATOR_DISABLE_RELAY);
2920 TestLoopbackCall();
2921}
2922
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002923// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002924TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002925 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002926 cricket::PORTALLOCATOR_ENABLE_BUNDLE |
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00002927 cricket::PORTALLOCATOR_DISABLE_TCP |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00002928 cricket::PORTALLOCATOR_DISABLE_RELAY);
2929 TestLoopbackCall();
2930}
2931
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002932TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002933 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002934 cricket::MediaSessionOptions options;
2935 options.has_audio = true;
2936 options.has_video = true;
2937
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002938 cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
2939 std::string error_code_str = "ERROR_CONTENT";
2940 std::string error_desc = "Fake session error description.";
2941 session_->SetError(error_code, error_desc);
2942
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002943 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2944 SessionDescriptionInterface* answer =
2945 CreateRemoteAnswer(offer, options);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002946
2947 std::string action;
2948 std::ostringstream session_error_msg;
2949 session_error_msg << kSessionError << error_code_str << ". ";
2950 session_error_msg << kSessionErrorDesc << error_desc << ".";
2951 SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
2952 SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002953}
2954
2955TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2956 constraints_.reset(new FakeConstraints());
2957 constraints_->AddOptional(
2958 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002959 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002960
2961 SetLocalDescriptionWithDataChannel();
2962 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2963}
2964
2965TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2966 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2967
2968 constraints_.reset(new FakeConstraints());
2969 constraints_->AddOptional(
2970 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org97077a32013-10-25 21:18:33 +00002971 options_.disable_sctp_data_channels = false;
2972
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002973 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002974
2975 SetLocalDescriptionWithDataChannel();
2976 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2977}
2978
wu@webrtc.org967bfff2013-09-19 05:49:50 +00002979TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2980 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2981
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002982 InitWithDtls();
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00002983
2984 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2985 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002986 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2987}
2988
2989TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2990 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2991 SetFactoryDtlsSrtp();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002992 InitWithDtls();
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002993
2994 // Create remote offer with SCTP.
2995 cricket::MediaSessionOptions options;
2996 options.data_channel_type = cricket::DCT_SCTP;
2997 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00002998 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00002999 SetRemoteDescriptionWithoutError(offer);
3000
3001 // Verifies the answer contains SCTP.
3002 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
3003 EXPECT_TRUE(answer != NULL);
3004 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
3005 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003006}
3007
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003008TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
3009 constraints_.reset(new FakeConstraints());
3010 constraints_->AddOptional(
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003011 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003012 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003013
3014 SetLocalDescriptionWithDataChannel();
3015 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3016}
3017
3018TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
3019 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3020
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003021 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003022
3023 SetLocalDescriptionWithDataChannel();
3024 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3025}
wu@webrtc.org91053e72013-08-10 07:18:04 +00003026
wu@webrtc.org97077a32013-10-25 21:18:33 +00003027TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
3028 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3029 options_.disable_sctp_data_channels = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003030 InitWithDtls();
wu@webrtc.org97077a32013-10-25 21:18:33 +00003031
3032 SetLocalDescriptionWithDataChannel();
3033 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3034}
3035
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003036TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
3037 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3038 const int new_send_port = 9998;
3039 const int new_recv_port = 7775;
3040
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003041 InitWithDtls();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003042 SetFactoryDtlsSrtp();
3043
3044 // By default, don't actually add the codecs to desc_factory_; they don't
3045 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
3046 // let the session description get parsed. That'll get the proper codecs
3047 // into the stream.
3048 cricket::MediaSessionOptions options;
3049 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
3050 "stream1", new_send_port, options);
3051
3052 // SetRemoteDescription will take the ownership of the offer.
3053 SetRemoteDescriptionWithoutError(offer);
3054
3055 SessionDescriptionInterface* answer = ChangeSDPSctpPort(
3056 new_recv_port, CreateAnswer(NULL));
3057 ASSERT_TRUE(answer != NULL);
3058
3059 // Now set the local description, which'll take ownership of the answer.
3060 SetLocalDescriptionWithoutError(answer);
3061
3062 // TEST PLAN: Set the port number to something new, set it in the SDP,
3063 // and pass it all the way down.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00003064 webrtc::InternalDataChannelInit dci;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003065 dci.reliable = true;
3066 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3067 talk_base::scoped_refptr<webrtc::DataChannel> dc =
3068 session_->CreateDataChannel("datachannel", &dci);
3069
3070 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
3071 int portnum = -1;
3072 ASSERT_TRUE(ch != NULL);
3073 ASSERT_EQ(1UL, ch->send_codecs().size());
3074 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
3075 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3076 ch->send_codecs()[0].name.c_str()));
3077 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
3078 &portnum));
3079 EXPECT_EQ(new_send_port, portnum);
3080
3081 ASSERT_EQ(1UL, ch->recv_codecs().size());
3082 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
3083 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3084 ch->recv_codecs()[0].name.c_str()));
3085 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
3086 &portnum));
3087 EXPECT_EQ(new_recv_port, portnum);
3088}
3089
wu@webrtc.org91053e72013-08-10 07:18:04 +00003090// Verifies that CreateOffer succeeds when CreateOffer is called before async
3091// identity generation is finished.
3092TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
3093 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003094 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003095
3096 EXPECT_TRUE(session_->waiting_for_identity());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003097 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003098 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3099 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003100 VerifyNoCryptoParams(offer->description(), true);
3101 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003102}
3103
3104// Verifies that CreateAnswer succeeds when CreateOffer is called before async
3105// identity generation is finished.
3106TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
3107 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003108 InitWithDtls();
3109 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003110
3111 cricket::MediaSessionOptions options;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003112 options.has_video = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003113 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003114 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003115 ASSERT_TRUE(offer.get() != NULL);
3116 SetRemoteDescriptionWithoutError(offer.release());
3117
3118 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
3119 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003120 VerifyNoCryptoParams(answer->description(), true);
3121 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003122}
3123
3124// Verifies that CreateOffer succeeds when CreateOffer is called after async
3125// identity generation is finished.
3126TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
3127 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003128 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003129
3130 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3131 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3132 EXPECT_TRUE(offer != NULL);
3133}
3134
3135// Verifies that CreateOffer fails when CreateOffer is called after async
3136// identity generation fails.
3137TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
3138 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00003139 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003140
3141 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
3142 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
3143 EXPECT_TRUE(offer == NULL);
3144}
3145
3146// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
3147// before async identity generation is finished.
3148TEST_F(WebRtcSessionTest,
3149 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
3150 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3151 VerifyMultipleAsyncCreateDescription(
3152 true, CreateSessionDescriptionRequest::kOffer);
3153}
3154
3155// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
3156// before async identity generation fails.
3157TEST_F(WebRtcSessionTest,
3158 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
3159 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3160 VerifyMultipleAsyncCreateDescription(
3161 false, CreateSessionDescriptionRequest::kOffer);
3162}
3163
3164// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
3165// before async identity generation is finished.
3166TEST_F(WebRtcSessionTest,
3167 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
3168 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3169 VerifyMultipleAsyncCreateDescription(
3170 true, CreateSessionDescriptionRequest::kAnswer);
3171}
3172
3173// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
3174// before async identity generation fails.
3175TEST_F(WebRtcSessionTest,
3176 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
3177 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
3178 VerifyMultipleAsyncCreateDescription(
3179 false, CreateSessionDescriptionRequest::kAnswer);
3180}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003181
3182// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
3183// offer has no SDES crypto but only DTLS fingerprint.
3184TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
3185 // Init without DTLS.
3186 Init(NULL);
3187 // Create a remote offer with secured transport disabled.
3188 cricket::MediaSessionOptions options;
3189 JsepSessionDescription* offer(CreateRemoteOffer(
3190 options, cricket::SEC_DISABLED));
3191 // Adds a DTLS fingerprint to the remote offer.
3192 cricket::SessionDescription* sdp = offer->description();
3193 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
3194 ASSERT_TRUE(audio != NULL);
3195 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
3196 audio->description.identity_fingerprint.reset(
3197 talk_base::SSLFingerprint::CreateFromRfc4572(
3198 talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003199 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003200 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003201}
3202
wu@webrtc.orgde305012013-10-31 15:40:38 +00003203// This test verifies DSCP is properly applied on the media channels.
3204TEST_F(WebRtcSessionTest, TestDscpConstraint) {
3205 constraints_.reset(new FakeConstraints());
3206 constraints_->AddOptional(
3207 webrtc::MediaConstraintsInterface::kEnableDscp, true);
3208 Init(NULL);
3209 mediastream_signaling_.SendAudioVideoStream1();
3210 SessionDescriptionInterface* offer = CreateOffer(NULL);
3211
3212 SetLocalDescriptionWithoutError(offer);
3213
3214 video_channel_ = media_engine_->GetVideoChannel(0);
3215 voice_channel_ = media_engine_->GetVoiceChannel(0);
3216
3217 ASSERT_TRUE(video_channel_ != NULL);
3218 ASSERT_TRUE(voice_channel_ != NULL);
3219 cricket::AudioOptions audio_options;
3220 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
3221 cricket::VideoOptions video_options;
3222 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3223 EXPECT_TRUE(audio_options.dscp.IsSet());
3224 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
3225 EXPECT_TRUE(video_options.dscp.IsSet());
3226 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
3227}
3228
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003229TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) {
3230 constraints_.reset(new FakeConstraints());
3231 constraints_->AddOptional(
3232 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
3233 true);
3234 Init(NULL);
3235 mediastream_signaling_.SendAudioVideoStream1();
3236 SessionDescriptionInterface* offer = CreateOffer(NULL);
3237
3238 SetLocalDescriptionWithoutError(offer);
3239
3240 video_channel_ = media_engine_->GetVideoChannel(0);
3241
3242 ASSERT_TRUE(video_channel_ != NULL);
3243 cricket::VideoOptions video_options;
3244 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3245 EXPECT_TRUE(
3246 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false));
3247}
3248
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003249// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
3250// currently fails because upon disconnection and reconnection OnIceComplete is
3251// called more than once without returning to IceGatheringGathering.