blob: f998ca8848c513c3c402170a393aaed3fc906fca [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2012 Google Inc.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004 *
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
deadbeefcbecd352015-09-23 11:50:27 -070028#include <vector>
29
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030#include "talk/app/webrtc/audiotrack.h"
jbauchac8869e2015-07-03 01:36:14 -070031#include "talk/app/webrtc/fakemetricsobserver.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032#include "talk/app/webrtc/jsepicecandidate.h"
33#include "talk/app/webrtc/jsepsessiondescription.h"
deadbeefab9b2d12015-10-14 11:33:11 -070034#include "talk/app/webrtc/peerconnection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035#include "talk/app/webrtc/mediastreamsignaling.h"
deadbeefab9b2d12015-10-14 11:33:11 -070036#include "talk/app/webrtc/sctputils.h"
37#include "talk/app/webrtc/streamcollection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000038#include "talk/app/webrtc/streamcollection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039#include "talk/app/webrtc/test/fakeconstraints.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020040#include "talk/app/webrtc/test/fakedtlsidentitystore.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000041#include "talk/app/webrtc/videotrack.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042#include "talk/app/webrtc/webrtcsession.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000043#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000044#include "talk/media/base/fakemediaengine.h"
45#include "talk/media/base/fakevideorenderer.h"
46#include "talk/media/base/mediachannel.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000047#include "webrtc/p2p/base/stunserver.h"
48#include "webrtc/p2p/base/teststunserver.h"
49#include "webrtc/p2p/base/testturnserver.h"
pthatcher@webrtc.orgb4aac132015-03-13 18:25:21 +000050#include "webrtc/p2p/base/transportchannel.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000051#include "webrtc/p2p/client/basicportallocator.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000052#include "talk/session/media/channelmanager.h"
53#include "talk/session/media/mediasession.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000054#include "webrtc/base/fakenetwork.h"
55#include "webrtc/base/firewallsocketserver.h"
56#include "webrtc/base/gunit.h"
57#include "webrtc/base/logging.h"
58#include "webrtc/base/network.h"
59#include "webrtc/base/physicalsocketserver.h"
60#include "webrtc/base/ssladapter.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020061#include "webrtc/base/sslidentity.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000062#include "webrtc/base/sslstreamadapter.h"
63#include "webrtc/base/stringutils.h"
64#include "webrtc/base/thread.h"
65#include "webrtc/base/virtualsocketserver.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066
67#define MAYBE_SKIP_TEST(feature) \
68 if (!(feature())) { \
69 LOG(LS_INFO) << "Feature disabled... skipping"; \
70 return; \
71 }
72
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073using cricket::DF_PLAY;
74using cricket::DF_SEND;
75using cricket::FakeVoiceMediaChannel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076using cricket::TransportInfo;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000077using rtc::SocketAddress;
78using rtc::scoped_ptr;
79using rtc::Thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000081using webrtc::CreateSessionDescriptionObserver;
82using webrtc::CreateSessionDescriptionRequest;
deadbeefab9b2d12015-10-14 11:33:11 -070083using webrtc::DataChannel;
Henrik Boström5e56c592015-08-11 10:33:13 +020084using webrtc::DtlsIdentityStoreInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085using webrtc::FakeConstraints;
jbauchac8869e2015-07-03 01:36:14 -070086using webrtc::FakeMetricsObserver;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::IceCandidateCollection;
deadbeefab9b2d12015-10-14 11:33:11 -070088using webrtc::InternalDataChannelInit;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089using webrtc::JsepIceCandidate;
90using webrtc::JsepSessionDescription;
wu@webrtc.org97077a32013-10-25 21:18:33 +000091using webrtc::PeerConnectionFactoryInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092using webrtc::PeerConnectionInterface;
93using webrtc::SessionDescriptionInterface;
deadbeefd59daf82015-10-14 15:02:44 -070094using webrtc::SessionStats;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000096using webrtc::WebRtcSession;
wu@webrtc.org364f2042013-11-20 21:49:41 +000097using webrtc::kBundleWithoutRtcpMux;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000098using webrtc::kCreateChannelFailed;
99using webrtc::kInvalidSdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100using webrtc::kMlineMismatch;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000101using webrtc::kPushDownTDFailed;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000102using webrtc::kSdpWithoutIceUfragPwd;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000103using webrtc::kSdpWithoutDtlsFingerprint;
104using webrtc::kSdpWithoutSdesCrypto;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000105using webrtc::kSessionError;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000106using webrtc::kSessionErrorDesc;
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000107using webrtc::kMaxUnsignalledRecvStreams;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000109typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
110
wu@webrtc.org364f2042013-11-20 21:49:41 +0000111static const int kClientAddrPort = 0;
112static const char kClientAddrHost1[] = "11.11.11.11";
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000113static const char kClientIPv6AddrHost1[] =
114 "2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff";
wu@webrtc.org364f2042013-11-20 21:49:41 +0000115static const char kClientAddrHost2[] = "22.22.22.22";
116static const char kStunAddrHost[] = "99.99.99.1";
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000117static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
118static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +0000119static const char kTurnUsername[] = "test";
120static const char kTurnPassword[] = "test";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000121
122static const char kSessionVersion[] = "1";
123
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124// Media index of candidates belonging to the first media content.
125static const int kMediaContentIndex0 = 0;
126static const char kMediaContentName0[] = "audio";
127
128// Media index of candidates belonging to the second media content.
129static const int kMediaContentIndex1 = 1;
130static const char kMediaContentName1[] = "video";
131
132static const int kIceCandidatesTimeout = 10000;
133
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000134static const char kFakeDtlsFingerprint[] =
135 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
136 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
137
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000138static const char kTooLongIceUfragPwd[] =
139 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
140 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
141 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
142 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag";
143
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000144static const char kSdpWithRtx[] =
145 "v=0\r\n"
146 "o=- 4104004319237231850 2 IN IP4 127.0.0.1\r\n"
147 "s=-\r\n"
148 "t=0 0\r\n"
149 "a=msid-semantic: WMS stream1\r\n"
150 "m=video 9 RTP/SAVPF 0 96\r\n"
151 "c=IN IP4 0.0.0.0\r\n"
152 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
153 "a=ice-ufrag:CerjGp19G7wpXwl7\r\n"
154 "a=ice-pwd:cMvOlFvQ6ochez1ZOoC2uBEC\r\n"
155 "a=mid:video\r\n"
156 "a=sendrecv\r\n"
157 "a=rtcp-mux\r\n"
158 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 "
159 "inline:5/4N5CDvMiyDArHtBByUM71VIkguH17ZNoX60GrA\r\n"
160 "a=rtpmap:0 fake_video_codec/90000\r\n"
161 "a=rtpmap:96 rtx/90000\r\n"
162 "a=fmtp:96 apt=0\r\n";
163
deadbeefab9b2d12015-10-14 11:33:11 -0700164static const char kStream1[] = "stream1";
165static const char kVideoTrack1[] = "video1";
166static const char kAudioTrack1[] = "audio1";
167
168static const char kStream2[] = "stream2";
169static const char kVideoTrack2[] = "video2";
170static const char kAudioTrack2[] = "audio2";
171
Henrik Boström87713d02015-08-25 09:53:21 +0200172enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
173
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000174// Add some extra |newlines| to the |message| after |line|.
175static void InjectAfter(const std::string& line,
176 const std::string& newlines,
177 std::string* message) {
178 const std::string tmp = line + newlines;
deadbeefcbecd352015-09-23 11:50:27 -0700179 rtc::replace_substrs(line.c_str(), line.length(), tmp.c_str(), tmp.length(),
180 message);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181}
182
183class MockIceObserver : public webrtc::IceObserver {
184 public:
185 MockIceObserver()
186 : oncandidatesready_(false),
187 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
188 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
189 }
190
191 virtual void OnIceConnectionChange(
192 PeerConnectionInterface::IceConnectionState new_state) {
193 ice_connection_state_ = new_state;
194 }
195 virtual void OnIceGatheringChange(
196 PeerConnectionInterface::IceGatheringState new_state) {
197 // We can never transition back to "new".
198 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
199 ice_gathering_state_ = new_state;
200
201 // oncandidatesready_ really means "ICE gathering is complete".
202 // This if statement ensures that this value remains correct when we
203 // transition from kIceGatheringComplete to kIceGatheringGathering.
204 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
205 oncandidatesready_ = false;
206 }
207 }
208
209 // Found a new candidate.
210 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000211 switch (candidate->sdp_mline_index()) {
212 case kMediaContentIndex0:
213 mline_0_candidates_.push_back(candidate->candidate());
214 break;
215 case kMediaContentIndex1:
216 mline_1_candidates_.push_back(candidate->candidate());
217 break;
218 default:
219 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000220 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000221
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 // The ICE gathering state should always be Gathering when a candidate is
223 // received (or possibly Completed in the case of the final candidate).
224 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
225 }
226
227 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
228 virtual void OnIceComplete() {
229 EXPECT_FALSE(oncandidatesready_);
230 oncandidatesready_ = true;
231
232 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
233 // be called approximately simultaneously. For ease of testing, this
234 // check additionally requires that they be called in the above order.
235 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
236 ice_gathering_state_);
237 }
238
239 bool oncandidatesready_;
240 std::vector<cricket::Candidate> mline_0_candidates_;
241 std::vector<cricket::Candidate> mline_1_candidates_;
242 PeerConnectionInterface::IceConnectionState ice_connection_state_;
243 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
244};
245
246class WebRtcSessionForTest : public webrtc::WebRtcSession {
247 public:
248 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000249 rtc::Thread* signaling_thread,
250 rtc::Thread* worker_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251 cricket::PortAllocator* port_allocator,
deadbeefab9b2d12015-10-14 11:33:11 -0700252 webrtc::IceObserver* ice_observer)
253 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000254 RegisterIceObserver(ice_observer);
255 }
256 virtual ~WebRtcSessionForTest() {}
257
deadbeefcbecd352015-09-23 11:50:27 -0700258 // Note that these methods are only safe to use if the signaling thread
259 // is the same as the worker thread
260 cricket::TransportChannel* voice_rtp_transport_channel() {
261 return rtp_transport_channel(voice_channel());
262 }
263
264 cricket::TransportChannel* voice_rtcp_transport_channel() {
265 return rtcp_transport_channel(voice_channel());
266 }
267
268 cricket::TransportChannel* video_rtp_transport_channel() {
269 return rtp_transport_channel(video_channel());
270 }
271
272 cricket::TransportChannel* video_rtcp_transport_channel() {
273 return rtcp_transport_channel(video_channel());
274 }
275
276 cricket::TransportChannel* data_rtp_transport_channel() {
277 return rtp_transport_channel(data_channel());
278 }
279
280 cricket::TransportChannel* data_rtcp_transport_channel() {
281 return rtcp_transport_channel(data_channel());
282 }
283
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 using webrtc::WebRtcSession::SetAudioPlayout;
285 using webrtc::WebRtcSession::SetAudioSend;
286 using webrtc::WebRtcSession::SetCaptureDevice;
287 using webrtc::WebRtcSession::SetVideoPlayout;
288 using webrtc::WebRtcSession::SetVideoSend;
deadbeefcbecd352015-09-23 11:50:27 -0700289
290 private:
291 cricket::TransportChannel* rtp_transport_channel(cricket::BaseChannel* ch) {
292 if (!ch) {
293 return nullptr;
294 }
295 return ch->transport_channel();
296 }
297
298 cricket::TransportChannel* rtcp_transport_channel(cricket::BaseChannel* ch) {
299 if (!ch) {
300 return nullptr;
301 }
302 return ch->rtcp_transport_channel();
303 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304};
305
wu@webrtc.org91053e72013-08-10 07:18:04 +0000306class WebRtcSessionCreateSDPObserverForTest
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000307 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000309 enum State {
310 kInit,
311 kFailed,
312 kSucceeded,
313 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000314 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000315
316 // CreateSessionDescriptionObserver implementation.
317 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000318 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000319 state_ = kSucceeded;
320 }
321 virtual void OnFailure(const std::string& error) {
322 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323 }
324
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000325 SessionDescriptionInterface* description() { return description_.get(); }
326
327 SessionDescriptionInterface* ReleaseDescription() {
328 return description_.release();
329 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330
wu@webrtc.org91053e72013-08-10 07:18:04 +0000331 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000332
wu@webrtc.org91053e72013-08-10 07:18:04 +0000333 protected:
334 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335
336 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000337 rtc::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000338 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000339};
340
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000341class FakeAudioRenderer : public cricket::AudioRenderer {
342 public:
solenberg98c68862015-10-09 03:27:14 -0700343 FakeAudioRenderer() : sink_(NULL) {}
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000344 virtual ~FakeAudioRenderer() {
345 if (sink_)
346 sink_->OnClose();
347 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000348
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000349 void SetSink(Sink* sink) override { sink_ = sink; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000350
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000351 cricket::AudioRenderer::Sink* sink() const { return sink_; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000352 private:
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000353 cricket::AudioRenderer::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000354};
355
Henrik Boström87713d02015-08-25 09:53:21 +0200356class WebRtcSessionTest
deadbeefab9b2d12015-10-14 11:33:11 -0700357 : public testing::TestWithParam<RTCCertificateGenerationMethod>,
358 public sigslot::has_slots<> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 protected:
360 // TODO Investigate why ChannelManager crashes, if it's created
361 // after stun_server.
362 WebRtcSessionTest()
363 : media_engine_(new cricket::FakeMediaEngine()),
364 data_engine_(new cricket::FakeDataEngine()),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 channel_manager_(new cricket::ChannelManager(
solenbergfacbbec2015-09-24 00:41:50 -0700366 media_engine_, data_engine_, new cricket::CaptureManager(),
367 rtc::Thread::Current())),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 tdesc_factory_(new cricket::TransportDescriptionFactory()),
369 desc_factory_(new cricket::MediaSessionDescriptionFactory(
370 channel_manager_.get(), tdesc_factory_.get())),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000371 pss_(new rtc::PhysicalSocketServer),
372 vss_(new rtc::VirtualSocketServer(pss_.get())),
373 fss_(new rtc::FirewallSocketServer(vss_.get())),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000374 ss_scope_(fss_.get()),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000375 stun_socket_addr_(rtc::SocketAddress(kStunAddrHost,
wu@webrtc.org364f2042013-11-20 21:49:41 +0000376 cricket::STUN_SERVER_PORT)),
jiayl@webrtc.orgbebc75e2014-09-26 23:01:11 +0000377 stun_server_(cricket::TestStunServer::Create(Thread::Current(),
378 stun_socket_addr_)),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000379 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
jbauchac8869e2015-07-03 01:36:14 -0700380 metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) {
buildbot@webrtc.org51c55082014-07-28 22:26:15 +0000381 cricket::ServerAddresses stun_servers;
382 stun_servers.insert(stun_socket_addr_);
383 allocator_.reset(new cricket::BasicPortAllocator(
384 &network_manager_,
385 stun_servers,
386 SocketAddress(), SocketAddress(), SocketAddress()));
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000387 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700388 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000389 EXPECT_TRUE(channel_manager_->Init());
390 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000391 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392 }
393
394 void AddInterface(const SocketAddress& addr) {
395 network_manager_.AddInterface(addr);
396 }
397
Henrik Boström87713d02015-08-25 09:53:21 +0200398 // If |dtls_identity_store| != null or |rtc_configuration| contains
399 // |certificates| then DTLS will be enabled unless explicitly disabled by
400 // |rtc_configuration| options. When DTLS is enabled a certificate will be
401 // used if provided, otherwise one will be generated using the
402 // |dtls_identity_store|.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000403 void Init(
Henrik Boström5e56c592015-08-11 10:33:13 +0200404 rtc::scoped_ptr<webrtc::DtlsIdentityStoreInterface> dtls_identity_store,
Henrik Lundin64dad832015-05-11 12:44:23 +0200405 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000406 ASSERT_TRUE(session_.get() == NULL);
407 session_.reset(new WebRtcSessionForTest(
deadbeefab9b2d12015-10-14 11:33:11 -0700408 channel_manager_.get(), rtc::Thread::Current(), rtc::Thread::Current(),
409 allocator_.get(), &observer_));
410 session_->SignalDataChannelOpenMessage.connect(
411 this, &WebRtcSessionTest::OnDataChannelOpenMessage);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412
413 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
414 observer_.ice_connection_state_);
415 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
416 observer_.ice_gathering_state_);
417
deadbeefcbecd352015-09-23 11:50:27 -0700418 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
419 dtls_identity_store.Pass(),
420 rtc_configuration));
jbauchac8869e2015-07-03 01:36:14 -0700421 session_->set_metrics_observer(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000422 }
423
deadbeefab9b2d12015-10-14 11:33:11 -0700424 void OnDataChannelOpenMessage(const std::string& label,
425 const InternalDataChannelInit& config) {
426 last_data_channel_label_ = label;
427 last_data_channel_config_ = config;
428 }
429
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000430 void Init() {
Henrik Lundin64dad832015-05-11 12:44:23 +0200431 PeerConnectionInterface::RTCConfiguration configuration;
Henrik Boström5e56c592015-08-11 10:33:13 +0200432 Init(nullptr, configuration);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000433 }
434
435 void InitWithIceTransport(
436 PeerConnectionInterface::IceTransportsType ice_transport_type) {
Henrik Lundin64dad832015-05-11 12:44:23 +0200437 PeerConnectionInterface::RTCConfiguration configuration;
438 configuration.type = ice_transport_type;
Henrik Boström5e56c592015-08-11 10:33:13 +0200439 Init(nullptr, configuration);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000440 }
441
442 void InitWithBundlePolicy(
443 PeerConnectionInterface::BundlePolicy bundle_policy) {
Henrik Lundin64dad832015-05-11 12:44:23 +0200444 PeerConnectionInterface::RTCConfiguration configuration;
Henrik Lundin64dad832015-05-11 12:44:23 +0200445 configuration.bundle_policy = bundle_policy;
Henrik Boström5e56c592015-08-11 10:33:13 +0200446 Init(nullptr, configuration);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -0700447 }
448
449 void InitWithRtcpMuxPolicy(
450 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) {
451 PeerConnectionInterface::RTCConfiguration configuration;
452 configuration.rtcp_mux_policy = rtcp_mux_policy;
Henrik Boström5e56c592015-08-11 10:33:13 +0200453 Init(nullptr, configuration);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000454 }
455
Henrik Boström87713d02015-08-25 09:53:21 +0200456 // Successfully init with DTLS; with a certificate generated and supplied or
457 // with a store that generates it for us.
458 void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) {
459 rtc::scoped_ptr<FakeDtlsIdentityStore> dtls_identity_store;
460 PeerConnectionInterface::RTCConfiguration configuration;
461 if (cert_gen_method == ALREADY_GENERATED) {
462 configuration.certificates.push_back(
463 FakeDtlsIdentityStore::GenerateCertificate());
464 } else if (cert_gen_method == DTLS_IDENTITY_STORE) {
465 dtls_identity_store.reset(new FakeDtlsIdentityStore());
466 dtls_identity_store->set_should_fail(false);
467 } else {
henrikg91d6ede2015-09-17 00:24:34 -0700468 RTC_CHECK(false);
Henrik Boström87713d02015-08-25 09:53:21 +0200469 }
470 Init(dtls_identity_store.Pass(), configuration);
471 }
472
473 // Init with DTLS with a store that will fail to generate a certificate.
474 void InitWithDtlsIdentityGenFail() {
Henrik Boström5e56c592015-08-11 10:33:13 +0200475 rtc::scoped_ptr<FakeDtlsIdentityStore> dtls_identity_store(
476 new FakeDtlsIdentityStore());
Henrik Boström87713d02015-08-25 09:53:21 +0200477 dtls_identity_store->set_should_fail(true);
Henrik Lundin64dad832015-05-11 12:44:23 +0200478 PeerConnectionInterface::RTCConfiguration configuration;
Henrik Boström5e56c592015-08-11 10:33:13 +0200479 Init(dtls_identity_store.Pass(), configuration);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000480 }
481
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000482 void InitWithDtmfCodec() {
483 // Add kTelephoneEventCodec for dtmf test.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000484 const cricket::AudioCodec kTelephoneEventCodec(
485 106, "telephone-event", 8000, 0, 1, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 std::vector<cricket::AudioCodec> codecs;
487 codecs.push_back(kTelephoneEventCodec);
488 media_engine_->SetAudioCodecs(codecs);
489 desc_factory_->set_audio_codecs(codecs);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000490 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 }
492
deadbeefab9b2d12015-10-14 11:33:11 -0700493 void SendAudioVideoStream1() {
494 send_stream_1_ = true;
495 send_stream_2_ = false;
496 send_audio_ = true;
497 send_video_ = true;
498 }
499
500 void SendAudioVideoStream2() {
501 send_stream_1_ = false;
502 send_stream_2_ = true;
503 send_audio_ = true;
504 send_video_ = true;
505 }
506
507 void SendAudioVideoStream1And2() {
508 send_stream_1_ = true;
509 send_stream_2_ = true;
510 send_audio_ = true;
511 send_video_ = true;
512 }
513
514 void SendNothing() {
515 send_stream_1_ = false;
516 send_stream_2_ = false;
517 send_audio_ = false;
518 send_video_ = false;
519 }
520
521 void SendAudioOnlyStream2() {
522 send_stream_1_ = false;
523 send_stream_2_ = true;
524 send_audio_ = true;
525 send_video_ = false;
526 }
527
528 void SendVideoOnlyStream2() {
529 send_stream_1_ = false;
530 send_stream_2_ = true;
531 send_audio_ = false;
532 send_video_ = true;
533 }
534
535 void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) {
536 if (send_stream_1_ && send_audio_) {
537 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1,
538 kStream1);
539 }
540 if (send_stream_1_ && send_video_) {
541 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1,
542 kStream1);
543 }
544 if (send_stream_2_ && send_audio_) {
545 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2,
546 kStream2);
547 }
548 if (send_stream_2_ && send_video_) {
549 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2,
550 kStream2);
551 }
552 if (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) {
553 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA,
554 data_channel_->label(),
555 data_channel_->label());
556 }
557 }
558
559 void GetOptionsForOffer(
560 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
561 cricket::MediaSessionOptions* session_options) {
562 AddStreamsToOptions(session_options);
563 ASSERT_TRUE(ConvertRtcOptionsForOffer(rtc_options, session_options));
564
565 if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) {
566 session_options->data_channel_type = cricket::DCT_SCTP;
567 }
568 }
569
570 void GetOptionsForAnswer(const webrtc::MediaConstraintsInterface* constraints,
571 cricket::MediaSessionOptions* session_options) {
572 AddStreamsToOptions(session_options);
573 session_options->recv_audio = false;
574 session_options->recv_video = false;
575 ASSERT_TRUE(ParseConstraintsForAnswer(constraints, session_options));
576
577 if (session_->data_channel_type() == cricket::DCT_SCTP) {
578 session_options->data_channel_type = cricket::DCT_SCTP;
579 }
580 }
581
582 // Creates a local offer and applies it. Starts ICE.
583 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584 // to decide which streams to create.
585 void InitiateCall() {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000586 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587 SetLocalDescriptionWithoutError(offer);
588 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
589 observer_.ice_gathering_state_,
590 kIceCandidatesTimeout);
591 }
592
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000593 SessionDescriptionInterface* CreateOffer() {
594 PeerConnectionInterface::RTCOfferAnswerOptions options;
595 options.offer_to_receive_audio =
596 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
597
598 return CreateOffer(options);
599 }
600
wu@webrtc.org91053e72013-08-10 07:18:04 +0000601 SessionDescriptionInterface* CreateOffer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000602 const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000603 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +0000604 observer = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -0700605 cricket::MediaSessionOptions session_options;
606 GetOptionsForOffer(options, &session_options);
607 session_->CreateOffer(observer, options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000608 EXPECT_TRUE_WAIT(
609 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000610 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000611 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000612 }
613
614 SessionDescriptionInterface* CreateAnswer(
615 const webrtc::MediaConstraintsInterface* constraints) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000616 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
wu@webrtc.org91053e72013-08-10 07:18:04 +0000617 = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -0700618 cricket::MediaSessionOptions session_options;
619 GetOptionsForAnswer(constraints, &session_options);
620 session_->CreateAnswer(observer, constraints, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000621 EXPECT_TRUE_WAIT(
622 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000623 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000624 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000625 }
626
wu@webrtc.org364f2042013-11-20 21:49:41 +0000627 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 return (session_->voice_channel() != NULL &&
629 session_->video_channel() != NULL);
630 }
631
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
633 ASSERT_TRUE(session_.get() != NULL);
634 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
635 ASSERT_TRUE(content != NULL);
636 const cricket::AudioContentDescription* audio_content =
637 static_cast<const cricket::AudioContentDescription*>(
638 content->description);
639 ASSERT_TRUE(audio_content != NULL);
640 ASSERT_EQ(1U, audio_content->cryptos().size());
641 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
642 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
643 audio_content->cryptos()[0].cipher_suite);
644 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
645 audio_content->protocol());
646
647 content = cricket::GetFirstVideoContent(sdp);
648 ASSERT_TRUE(content != NULL);
649 const cricket::VideoContentDescription* video_content =
650 static_cast<const cricket::VideoContentDescription*>(
651 content->description);
652 ASSERT_TRUE(video_content != NULL);
653 ASSERT_EQ(1U, video_content->cryptos().size());
654 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
655 video_content->cryptos()[0].cipher_suite);
656 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
657 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
658 video_content->protocol());
659 }
660
661 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
662 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
663 ASSERT_TRUE(content != NULL);
664 const cricket::AudioContentDescription* audio_content =
665 static_cast<const cricket::AudioContentDescription*>(
666 content->description);
667 ASSERT_TRUE(audio_content != NULL);
668 ASSERT_EQ(0U, audio_content->cryptos().size());
669
670 content = cricket::GetFirstVideoContent(sdp);
671 ASSERT_TRUE(content != NULL);
672 const cricket::VideoContentDescription* video_content =
673 static_cast<const cricket::VideoContentDescription*>(
674 content->description);
675 ASSERT_TRUE(video_content != NULL);
676 ASSERT_EQ(0U, video_content->cryptos().size());
677
678 if (dtls) {
deadbeeff3938292015-07-15 12:20:53 -0700679 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 audio_content->protocol());
deadbeeff3938292015-07-15 12:20:53 -0700681 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 video_content->protocol());
683 } else {
684 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
685 audio_content->protocol());
686 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
687 video_content->protocol());
688 }
689 }
690
691 // Set the internal fake description factories to do DTLS-SRTP.
692 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000693 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 std::string identity_name = "WebRTC" +
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000695 rtc::ToString(rtc::CreateRandomId());
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200696 // Confirmed to work with KT_RSA and KT_ECDSA.
Henrik Boström3a14bf32015-08-31 09:27:58 +0200697 tdesc_factory_->set_certificate(rtc::RTCCertificate::Create(
torbjorng335204c2015-10-08 02:30:14 -0700698 rtc::scoped_ptr<rtc::SSLIdentity>(rtc::SSLIdentity::Generate(
699 identity_name, rtc::KT_DEFAULT)).Pass()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
701 }
702
703 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
704 bool expected) {
705 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
706 ASSERT_TRUE(audio != NULL);
707 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000708 const TransportInfo* video = sdp->GetTransportInfoByName("video");
709 ASSERT_TRUE(video != NULL);
710 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000711 }
712
713 void VerifyAnswerFromNonCryptoOffer() {
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +0000714 // Create an SDP without Crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000715 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000716 options.recv_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000717 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000718 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000719 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000720 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000721 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
722 offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000723 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724 // Answer should be NULL as no crypto params in offer.
725 ASSERT_TRUE(answer == NULL);
726 }
727
728 void VerifyAnswerFromCryptoOffer() {
729 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000730 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000731 options.bundle_enabled = true;
732 scoped_ptr<JsepSessionDescription> offer(
733 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
734 ASSERT_TRUE(offer.get() != NULL);
735 VerifyCryptoParams(offer->description());
736 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000737 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738 ASSERT_TRUE(answer.get() != NULL);
739 VerifyCryptoParams(answer->description());
740 }
741
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000742 void SetAndVerifyNumUnsignalledRecvStreams(
743 int value_set, int value_expected) {
744 constraints_.reset(new FakeConstraints());
745 constraints_->AddOptional(
746 webrtc::MediaConstraintsInterface::kNumUnsignalledRecvStreams,
747 value_set);
748 session_.reset();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +0000749 Init();
deadbeefab9b2d12015-10-14 11:33:11 -0700750 SendAudioVideoStream1();
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000751 SessionDescriptionInterface* offer = CreateOffer();
752
753 SetLocalDescriptionWithoutError(offer);
754
755 video_channel_ = media_engine_->GetVideoChannel(0);
756
757 ASSERT_TRUE(video_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -0700758 const cricket::VideoOptions& video_options = video_channel_->options();
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000759 EXPECT_EQ(value_expected,
760 video_options.unsignalled_recv_stream_limit.GetWithDefaultIfUnset(-1));
761 }
762
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
764 const cricket::SessionDescription* desc2,
765 bool expect_equal) {
766 if (desc1->contents().size() != desc2->contents().size()) {
767 EXPECT_FALSE(expect_equal);
768 return;
769 }
770
771 const cricket::ContentInfos& contents = desc1->contents();
772 cricket::ContentInfos::const_iterator it = contents.begin();
773
774 for (; it != contents.end(); ++it) {
775 const cricket::TransportDescription* transport_desc1 =
776 desc1->GetTransportDescriptionByName(it->name);
777 const cricket::TransportDescription* transport_desc2 =
778 desc2->GetTransportDescriptionByName(it->name);
779 if (!transport_desc1 || !transport_desc2) {
780 EXPECT_FALSE(expect_equal);
781 return;
782 }
783 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
784 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
785 EXPECT_FALSE(expect_equal);
786 return;
787 }
788 }
789 EXPECT_TRUE(expect_equal);
790 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000791
792 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
793 std::string *sdp) {
794 const cricket::SessionDescription* desc = current_desc->description();
795 EXPECT_TRUE(current_desc->ToString(sdp));
796
797 const cricket::ContentInfos& contents = desc->contents();
798 cricket::ContentInfos::const_iterator it = contents.begin();
799 // Replace ufrag and pwd lines with empty strings.
800 for (; it != contents.end(); ++it) {
801 const cricket::TransportDescription* transport_desc =
802 desc->GetTransportDescriptionByName(it->name);
803 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
804 + "\r\n";
805 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
806 + "\r\n";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000807 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000808 "", 0,
809 sdp);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000810 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000811 "", 0,
812 sdp);
813 }
814 }
815
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000816 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
817 const std::string& modified_ice_ufrag,
818 const std::string& modified_ice_pwd,
819 std::string* sdp) {
820 const cricket::SessionDescription* desc = current_desc->description();
821 EXPECT_TRUE(current_desc->ToString(sdp));
822
823 const cricket::ContentInfos& contents = desc->contents();
824 cricket::ContentInfos::const_iterator it = contents.begin();
825 // Replace ufrag and pwd lines with |modified_ice_ufrag| and
826 // |modified_ice_pwd| strings.
827 for (; it != contents.end(); ++it) {
828 const cricket::TransportDescription* transport_desc =
829 desc->GetTransportDescriptionByName(it->name);
830 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
831 + "\r\n";
832 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
833 + "\r\n";
834 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n";
835 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000836 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000837 mod_ufrag.c_str(), mod_ufrag.length(),
838 sdp);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000839 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(),
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000840 mod_pwd.c_str(), mod_pwd.length(),
841 sdp);
842 }
843 }
844
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000845 // Creates a remote offer and and applies it as a remote description,
846 // creates a local answer and applies is as a local description.
deadbeefab9b2d12015-10-14 11:33:11 -0700847 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848 // to decide which local and remote streams to create.
849 void CreateAndSetRemoteOfferAndLocalAnswer() {
850 SessionDescriptionInterface* offer = CreateRemoteOffer();
851 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000852 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000853 SetLocalDescriptionWithoutError(answer);
854 }
855 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
856 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
deadbeefcbecd352015-09-23 11:50:27 -0700857 session_->MaybeStartGathering();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000858 }
859 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700860 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 SetLocalDescriptionWithoutError(desc);
862 EXPECT_EQ(expected_state, session_->state());
863 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000864 void SetLocalDescriptionExpectError(const std::string& action,
865 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000866 SessionDescriptionInterface* desc) {
867 std::string error;
868 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000869 std::string sdp_type = "local ";
870 sdp_type.append(action);
871 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000872 EXPECT_NE(std::string::npos, error.find(expected_error));
873 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000874 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
875 SessionDescriptionInterface* desc) {
876 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
877 expected_error, desc);
878 }
879 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
880 SessionDescriptionInterface* desc) {
881 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
882 expected_error, desc);
883 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000884 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
885 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
886 }
887 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
deadbeefd59daf82015-10-14 15:02:44 -0700888 WebRtcSession::State expected_state) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000889 SetRemoteDescriptionWithoutError(desc);
890 EXPECT_EQ(expected_state, session_->state());
891 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000892 void SetRemoteDescriptionExpectError(const std::string& action,
893 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 SessionDescriptionInterface* desc) {
895 std::string error;
896 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000897 std::string sdp_type = "remote ";
898 sdp_type.append(action);
899 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900 EXPECT_NE(std::string::npos, error.find(expected_error));
901 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000902 void SetRemoteDescriptionOfferExpectError(
903 const std::string& expected_error, SessionDescriptionInterface* desc) {
904 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
905 expected_error, desc);
906 }
907 void SetRemoteDescriptionPranswerExpectError(
908 const std::string& expected_error, SessionDescriptionInterface* desc) {
909 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
910 expected_error, desc);
911 }
912 void SetRemoteDescriptionAnswerExpectError(
913 const std::string& expected_error, SessionDescriptionInterface* desc) {
914 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
915 expected_error, desc);
916 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917
918 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
919 SessionDescriptionInterface** nocrypto_answer) {
920 // Create a SDP without Crypto.
921 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000922 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000923 options.bundle_enabled = true;
924 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
925 ASSERT_TRUE(*offer != NULL);
926 VerifyCryptoParams((*offer)->description());
927
928 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
929 cricket::SEC_DISABLED);
930 EXPECT_TRUE(*nocrypto_answer != NULL);
931 }
932
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000933 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
934 SessionDescriptionInterface** nodtls_answer) {
935 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000936 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000937 options.bundle_enabled = true;
938
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000939 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000940 CreateRemoteOffer(options, cricket::SEC_ENABLED));
941
942 *nodtls_answer =
943 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
944 EXPECT_TRUE(*nodtls_answer != NULL);
945 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
946 VerifyCryptoParams((*nodtls_answer)->description());
947
948 SetFactoryDtlsSrtp();
949 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
950 ASSERT_TRUE(*offer != NULL);
951 VerifyFingerprintStatus((*offer)->description(), true);
952 VerifyCryptoParams((*offer)->description());
953 }
954
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000955 JsepSessionDescription* CreateRemoteOfferWithVersion(
956 cricket::MediaSessionOptions options,
957 cricket::SecurePolicy secure_policy,
958 const std::string& session_version,
959 const SessionDescriptionInterface* current_desc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000960 std::string session_id = rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961 const cricket::SessionDescription* cricket_desc = NULL;
962 if (current_desc) {
963 cricket_desc = current_desc->description();
964 session_id = current_desc->session_id();
965 }
966
967 desc_factory_->set_secure(secure_policy);
968 JsepSessionDescription* offer(
969 new JsepSessionDescription(JsepSessionDescription::kOffer));
970 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
971 session_id, session_version)) {
972 delete offer;
973 offer = NULL;
974 }
975 return offer;
976 }
977 JsepSessionDescription* CreateRemoteOffer(
978 cricket::MediaSessionOptions options) {
979 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
980 kSessionVersion, NULL);
981 }
982 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000983 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
984 return CreateRemoteOfferWithVersion(
985 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 }
987 JsepSessionDescription* CreateRemoteOffer(
988 cricket::MediaSessionOptions options,
989 const SessionDescriptionInterface* current_desc) {
990 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
991 kSessionVersion, current_desc);
992 }
993
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000994 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
995 const char* sctp_stream_name, int new_port,
996 cricket::MediaSessionOptions options) {
997 options.data_channel_type = cricket::DCT_SCTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000998 options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel",
999 sctp_stream_name);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001000 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
1001 }
1002
1003 // Takes ownership of offer_basis (and deletes it).
1004 JsepSessionDescription* ChangeSDPSctpPort(
1005 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
1006 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
1007 // SessionDescription from the mutated string.
1008 const char* default_port_str = "5000";
1009 char new_port_str[16];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001010 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001011 std::string offer_str;
1012 offer_basis->ToString(&offer_str);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001013 rtc::replace_substrs(default_port_str, strlen(default_port_str),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00001014 new_port_str, strlen(new_port_str),
1015 &offer_str);
1016 JsepSessionDescription* offer = new JsepSessionDescription(
1017 offer_basis->type());
1018 delete offer_basis;
1019 offer->Initialize(offer_str, NULL);
1020 return offer;
1021 }
1022
deadbeefab9b2d12015-10-14 11:33:11 -07001023 // Create a remote offer. Call SendAudioVideoStreamX()
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001024 // before this function to decide which streams to create.
1025 JsepSessionDescription* CreateRemoteOffer() {
1026 cricket::MediaSessionOptions options;
deadbeefab9b2d12015-10-14 11:33:11 -07001027 GetOptionsForAnswer(NULL, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028 return CreateRemoteOffer(options, session_->remote_description());
1029 }
1030
1031 JsepSessionDescription* CreateRemoteAnswer(
1032 const SessionDescriptionInterface* offer,
1033 cricket::MediaSessionOptions options,
1034 cricket::SecurePolicy policy) {
1035 desc_factory_->set_secure(policy);
1036 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001037 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038 JsepSessionDescription* answer(
1039 new JsepSessionDescription(JsepSessionDescription::kAnswer));
1040 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
1041 options, NULL),
1042 session_id, kSessionVersion)) {
1043 delete answer;
1044 answer = NULL;
1045 }
1046 return answer;
1047 }
1048
1049 JsepSessionDescription* CreateRemoteAnswer(
1050 const SessionDescriptionInterface* offer,
1051 cricket::MediaSessionOptions options) {
1052 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
1053 }
1054
deadbeefab9b2d12015-10-14 11:33:11 -07001055 // Creates an answer session description.
1056 // Call SendAudioVideoStreamX() before this function
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001057 // to decide which streams to create.
1058 JsepSessionDescription* CreateRemoteAnswer(
1059 const SessionDescriptionInterface* offer) {
1060 cricket::MediaSessionOptions options;
deadbeefab9b2d12015-10-14 11:33:11 -07001061 GetOptionsForAnswer(NULL, &options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001062 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
1063 }
1064
1065 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001066 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001067 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001068 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001069
1070 PeerConnectionInterface::RTCOfferAnswerOptions options;
1071 options.use_rtp_mux = bundle;
1072
1073 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1075 // and answer.
1076 SetLocalDescriptionWithoutError(offer);
1077
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001078 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001079 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001080 std::string sdp;
1081 EXPECT_TRUE(answer->ToString(&sdp));
1082
1083 size_t expected_candidate_num = 2;
1084 if (!rtcp_mux) {
1085 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
1086 // for rtp and rtcp.
1087 expected_candidate_num = 4;
1088 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001089 const std::string kRtcpMux = "a=rtcp-mux";
1090 const std::string kXRtcpMux = "a=xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001091 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092 kXRtcpMux.c_str(), kXRtcpMux.length(),
1093 &sdp);
1094 }
1095
1096 SessionDescriptionInterface* new_answer = CreateSessionDescription(
1097 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001098
1099 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001100 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1102 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
deadbeefcbecd352015-09-23 11:50:27 -07001103 if (bundle) {
1104 EXPECT_EQ(0, observer_.mline_1_candidates_.size());
1105 } else {
1106 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001107 }
1108 }
1109 // Tests that we can only send DTMF when the dtmf codec is supported.
1110 void TestCanInsertDtmf(bool can) {
1111 if (can) {
1112 InitWithDtmfCodec();
1113 } else {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001114 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001115 }
deadbeefab9b2d12015-10-14 11:33:11 -07001116 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001117 CreateAndSetRemoteOfferAndLocalAnswer();
1118 EXPECT_FALSE(session_->CanInsertDtmf(""));
1119 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
1120 }
1121
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001122 // Helper class to configure loopback network and verify Best
1123 // Connection using right IP protocol for TestLoopbackCall
1124 // method. LoopbackNetworkManager applies firewall rules to block
1125 // all ping traffic once ICE completed, and remove them to observe
1126 // ICE reconnected again. This LoopbackNetworkConfiguration struct
1127 // verifies the best connection is using the right IP protocol after
1128 // initial ICE convergences.
1129
1130 class LoopbackNetworkConfiguration {
deadbeefcbecd352015-09-23 11:50:27 -07001131 public:
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001132 LoopbackNetworkConfiguration()
1133 : test_ipv6_network_(false),
1134 test_extra_ipv4_network_(false),
1135 best_connection_after_initial_ice_converged_(1, 0) {}
1136
1137 // Used to track the expected best connection count in each IP protocol.
1138 struct ExpectedBestConnection {
1139 ExpectedBestConnection(int ipv4_count, int ipv6_count)
1140 : ipv4_count_(ipv4_count),
1141 ipv6_count_(ipv6_count) {}
1142
1143 int ipv4_count_;
1144 int ipv6_count_;
1145 };
1146
1147 bool test_ipv6_network_;
1148 bool test_extra_ipv4_network_;
1149 ExpectedBestConnection best_connection_after_initial_ice_converged_;
1150
1151 void VerifyBestConnectionAfterIceConverge(
jbauchac8869e2015-07-03 01:36:14 -07001152 const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer) const {
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001153 Verify(metrics_observer, best_connection_after_initial_ice_converged_);
1154 }
1155
1156 private:
jbauchac8869e2015-07-03 01:36:14 -07001157 void Verify(const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer,
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001158 const ExpectedBestConnection& expected) const {
1159 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001160 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1161 webrtc::kBestConnections_IPv4),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001162 expected.ipv4_count_);
1163 EXPECT_EQ(
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001164 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily,
1165 webrtc::kBestConnections_IPv6),
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001166 expected.ipv6_count_);
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001167 // This is used in the loopback call so there is only single host to host
1168 // candidate pair.
1169 EXPECT_EQ(metrics_observer->GetEnumCounter(
1170 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1171 webrtc::kIceCandidatePairHostHost),
Guo-wei Shieh3cc834a2015-09-04 15:52:14 -07001172 0);
1173 EXPECT_EQ(metrics_observer->GetEnumCounter(
1174 webrtc::kEnumCounterIceCandidatePairTypeUdp,
1175 webrtc::kIceCandidatePairHostPublicHostPublic),
Guo-wei Shieh3d564c12015-08-19 16:51:15 -07001176 1);
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001177 }
1178 };
1179
1180 class LoopbackNetworkManager {
1181 public:
1182 LoopbackNetworkManager(WebRtcSessionTest* session,
1183 const LoopbackNetworkConfiguration& config)
1184 : config_(config) {
1185 session->AddInterface(
1186 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1187 if (config_.test_extra_ipv4_network_) {
1188 session->AddInterface(
1189 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1190 }
1191 if (config_.test_ipv6_network_) {
1192 session->AddInterface(
1193 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1194 }
1195 }
1196
1197 void ApplyFirewallRules(rtc::FirewallSocketServer* fss) {
1198 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1199 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1200 if (config_.test_extra_ipv4_network_) {
1201 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1202 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1203 }
1204 if (config_.test_ipv6_network_) {
1205 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1206 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1207 }
1208 }
1209
1210 void ClearRules(rtc::FirewallSocketServer* fss) { fss->ClearRules(); }
1211
1212 private:
1213 LoopbackNetworkConfiguration config_;
1214 };
1215
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216 // The method sets up a call from the session to itself, in a loopback
1217 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001218 // disconnection, and then a permanent disconnection.
1219 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001220 // by multiple tests with different allocators (e.g. with and without BUNDLE).
1221 // While running the call, this method also checks if the session goes through
1222 // the correct sequence of ICE states when a connection is established,
1223 // broken, and re-established.
1224 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001225 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
1226 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001227 // The Gathering state should go: New -> Gathering -> Completed.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001228
1229 void TestLoopbackCall(const LoopbackNetworkConfiguration& config) {
1230 LoopbackNetworkManager loopback_network_manager(this, config);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001231 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001232 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001233 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001234
1235 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1236 observer_.ice_gathering_state_);
1237 SetLocalDescriptionWithoutError(offer);
1238 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
1239 observer_.ice_connection_state_);
1240 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
1241 observer_.ice_gathering_state_,
1242 kIceCandidatesTimeout);
1243 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1244 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
1245 observer_.ice_gathering_state_,
1246 kIceCandidatesTimeout);
1247
1248 std::string sdp;
1249 offer->ToString(&sdp);
1250 SessionDescriptionInterface* desc =
jbauchfabe2c92015-07-16 13:43:14 -07001251 webrtc::CreateSessionDescription(
1252 JsepSessionDescription::kAnswer, sdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001253 ASSERT_TRUE(desc != NULL);
1254 SetRemoteDescriptionWithoutError(desc);
1255
1256 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
1257 observer_.ice_connection_state_,
1258 kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001259
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001260 // The ice connection state is "Connected" too briefly to catch in a test.
1261 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 observer_.ice_connection_state_,
1263 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001264
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001265 config.VerifyBestConnectionAfterIceConverge(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001266 // Adding firewall rule to block ping requests, which should cause
1267 // transport channel failure.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001268
1269 loopback_network_manager.ApplyFirewallRules(fss_.get());
1270
1271 LOG(LS_INFO) << "Firewall Rules applied";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
1273 observer_.ice_connection_state_,
1274 kIceCandidatesTimeout);
1275
jbauchac8869e2015-07-03 01:36:14 -07001276 metrics_observer_->Reset();
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001277
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001278 // Clearing the rules, session should move back to completed state.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001279 loopback_network_manager.ClearRules(fss_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001280
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001281 LOG(LS_INFO) << "Firewall Rules cleared";
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001282 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001283 observer_.ice_connection_state_,
1284 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001285
1286 // Now we block ping requests and wait until the ICE connection transitions
1287 // to the Failed state. This will take at least 30 seconds because it must
1288 // wait for the Port to timeout.
1289 int port_timeout = 30000;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001290
1291 loopback_network_manager.ApplyFirewallRules(fss_.get());
1292 LOG(LS_INFO) << "Firewall Rules applied again";
jlmiller@webrtc.org804eb462015-02-20 02:20:03 +00001293 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001294 observer_.ice_connection_state_,
1295 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001296 }
1297
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001298 void TestLoopbackCall() {
1299 LoopbackNetworkConfiguration config;
1300 TestLoopbackCall(config);
1301 }
1302
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001303 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
1304 void AddCNCodecs() {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001305 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
1306 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
1307
1308 // Add kCNCodec for dtmf test.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
1310 codecs.push_back(kCNCodec1);
1311 codecs.push_back(kCNCodec2);
1312 media_engine_->SetAudioCodecs(codecs);
1313 desc_factory_->set_audio_codecs(codecs);
1314 }
1315
1316 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
1317 const cricket::ContentDescription* description = content->description;
1318 ASSERT(description != NULL);
1319 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001320 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001321 ASSERT(audio_content_desc != NULL);
1322 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
1323 if (audio_content_desc->codecs()[i].name == "CN")
1324 return false;
1325 }
1326 return true;
1327 }
1328
deadbeefab9b2d12015-10-14 11:33:11 -07001329 void CreateDataChannel() {
deadbeeffc648b62015-10-13 16:42:33 -07001330 webrtc::InternalDataChannelInit dci;
deadbeefab9b2d12015-10-14 11:33:11 -07001331 dci.reliable = session_->data_channel_type() == cricket::DCT_SCTP;
1332 data_channel_ = DataChannel::Create(
1333 session_.get(), session_->data_channel_type(), "datachannel", dci);
1334 }
1335
1336 void SetLocalDescriptionWithDataChannel() {
1337 CreateDataChannel();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001338 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339 SetLocalDescriptionWithoutError(offer);
1340 }
1341
wu@webrtc.org91053e72013-08-10 07:18:04 +00001342 void VerifyMultipleAsyncCreateDescription(
Henrik Boström87713d02015-08-25 09:53:21 +02001343 RTCCertificateGenerationMethod cert_gen_method,
1344 CreateSessionDescriptionRequest::Type type) {
1345 InitWithDtls(cert_gen_method);
1346 VerifyMultipleAsyncCreateDescriptionAfterInit(true, type);
1347 }
1348
1349 void VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
1350 CreateSessionDescriptionRequest::Type type) {
1351 InitWithDtlsIdentityGenFail();
1352 VerifyMultipleAsyncCreateDescriptionAfterInit(false, type);
1353 }
1354
1355 void VerifyMultipleAsyncCreateDescriptionAfterInit(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001356 bool success, CreateSessionDescriptionRequest::Type type) {
henrikg91d6ede2015-09-17 00:24:34 -07001357 RTC_CHECK(session_);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001358 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001359 if (type == CreateSessionDescriptionRequest::kAnswer) {
1360 cricket::MediaSessionOptions options;
1361 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001362 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001363 ASSERT_TRUE(offer.get() != NULL);
1364 SetRemoteDescriptionWithoutError(offer.release());
1365 }
1366
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001367 PeerConnectionInterface::RTCOfferAnswerOptions options;
deadbeefab9b2d12015-10-14 11:33:11 -07001368 cricket::MediaSessionOptions session_options;
wu@webrtc.org91053e72013-08-10 07:18:04 +00001369 const int kNumber = 3;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001370 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +00001371 observers[kNumber];
1372 for (int i = 0; i < kNumber; ++i) {
1373 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
1374 if (type == CreateSessionDescriptionRequest::kOffer) {
deadbeefab9b2d12015-10-14 11:33:11 -07001375 session_->CreateOffer(observers[i], options, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001376 } else {
deadbeefab9b2d12015-10-14 11:33:11 -07001377 session_->CreateAnswer(observers[i], nullptr, session_options);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001378 }
1379 }
1380
1381 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1382 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1383 WebRtcSessionCreateSDPObserverForTest::kFailed;
1384
1385 for (int i = 0; i < kNumber; ++i) {
1386 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1387 if (success) {
1388 EXPECT_TRUE(observers[i]->description() != NULL);
1389 } else {
1390 EXPECT_TRUE(observers[i]->description() == NULL);
1391 }
1392 }
1393 }
1394
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001395 void ConfigureAllocatorWithTurn() {
1396 cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
1397 cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
1398 relay_server.credentials = credentials;
1399 relay_server.ports.push_back(cricket::ProtocolAddress(
1400 kTurnUdpIntAddr, cricket::PROTO_UDP, false));
1401 allocator_->AddRelay(relay_server);
1402 allocator_->set_step_delay(cricket::kMinimumStepDelay);
Peter Thatcher7cbd1882015-09-17 18:54:52 -07001403 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001404 }
1405
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001406 cricket::FakeMediaEngine* media_engine_;
1407 cricket::FakeDataEngine* data_engine_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001408 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
1409 rtc::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001410 rtc::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1411 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
1412 rtc::scoped_ptr<rtc::VirtualSocketServer> vss_;
1413 rtc::scoped_ptr<rtc::FirewallSocketServer> fss_;
1414 rtc::SocketServerScope ss_scope_;
1415 rtc::SocketAddress stun_socket_addr_;
jiayl@webrtc.orgbebc75e2014-09-26 23:01:11 +00001416 rtc::scoped_ptr<cricket::TestStunServer> stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001417 cricket::TestTurnServer turn_server_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001418 rtc::FakeNetworkManager network_manager_;
1419 rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001420 PeerConnectionFactoryInterface::Options options_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001421 rtc::scoped_ptr<FakeConstraints> constraints_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001422 rtc::scoped_ptr<WebRtcSessionForTest> session_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001423 MockIceObserver observer_;
1424 cricket::FakeVideoMediaChannel* video_channel_;
1425 cricket::FakeVoiceMediaChannel* voice_channel_;
jbauchac8869e2015-07-03 01:36:14 -07001426 rtc::scoped_refptr<FakeMetricsObserver> metrics_observer_;
deadbeefab9b2d12015-10-14 11:33:11 -07001427 // The following flags affect options created for CreateOffer/CreateAnswer.
1428 bool send_stream_1_ = false;
1429 bool send_stream_2_ = false;
1430 bool send_audio_ = false;
1431 bool send_video_ = false;
1432 rtc::scoped_refptr<DataChannel> data_channel_;
1433 // Last values received from data channel creation signal.
1434 std::string last_data_channel_label_;
1435 InternalDataChannelInit last_data_channel_config_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436};
1437
Henrik Boström87713d02015-08-25 09:53:21 +02001438TEST_P(WebRtcSessionTest, TestInitializeWithDtls) {
1439 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001440 // SDES is disabled when DTLS is on.
1441 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442}
1443
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001444TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001445 Init();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001446 // SDES is required if DTLS is off.
1447 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001448}
1449
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001450TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1451 TestSessionCandidatesWithBundleRtcpMux(false, false);
1452}
1453
1454// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1455// with rtcp-mux and/or bundle.
1456TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1457 TestSessionCandidatesWithBundleRtcpMux(false, true);
1458}
1459
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001460TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1461 TestSessionCandidatesWithBundleRtcpMux(true, true);
1462}
1463
1464TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001465 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1466 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001467 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001468 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469 InitiateCall();
1470 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1471 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1472 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1473}
1474
1475TEST_F(WebRtcSessionTest, TestStunError) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001476 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1477 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org364f2042013-11-20 21:49:41 +00001478 fss_->AddRule(false,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001479 rtc::FP_UDP,
1480 rtc::FD_ANY,
1481 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001482 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001483 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001484 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001485 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001486 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1487 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1488 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1489}
1490
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001491// Test session delivers no candidates gathered when constraint set to "none".
1492TEST_F(WebRtcSessionTest, TestIceTransportsNone) {
1493 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001494 InitWithIceTransport(PeerConnectionInterface::kNone);
deadbeefab9b2d12015-10-14 11:33:11 -07001495 SendAudioVideoStream1();
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001496 InitiateCall();
1497 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1498 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1499 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1500}
1501
1502// Test session delivers only relay candidates gathered when constaint set to
1503// "relay".
1504TEST_F(WebRtcSessionTest, TestIceTransportsRelay) {
1505 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1506 ConfigureAllocatorWithTurn();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001507 InitWithIceTransport(PeerConnectionInterface::kRelay);
deadbeefab9b2d12015-10-14 11:33:11 -07001508 SendAudioVideoStream1();
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001509 InitiateCall();
1510 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1511 EXPECT_EQ(2u, observer_.mline_0_candidates_.size());
1512 EXPECT_EQ(2u, observer_.mline_1_candidates_.size());
1513 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
1514 EXPECT_EQ(cricket::RELAY_PORT_TYPE,
1515 observer_.mline_0_candidates_[i].type());
1516 }
1517 for (size_t i = 0; i < observer_.mline_1_candidates_.size(); ++i) {
1518 EXPECT_EQ(cricket::RELAY_PORT_TYPE,
1519 observer_.mline_1_candidates_[i].type());
1520 }
1521}
1522
1523// Test session delivers all candidates gathered when constaint set to "all".
1524TEST_F(WebRtcSessionTest, TestIceTransportsAll) {
1525 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001526 InitWithIceTransport(PeerConnectionInterface::kAll);
deadbeefab9b2d12015-10-14 11:33:11 -07001527 SendAudioVideoStream1();
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001528 InitiateCall();
1529 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1530 // Host + STUN. By default allocator is disabled to gather relay candidates.
1531 EXPECT_EQ(4u, observer_.mline_0_candidates_.size());
1532 EXPECT_EQ(4u, observer_.mline_1_candidates_.size());
1533}
1534
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001535TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001536 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001537 SessionDescriptionInterface* offer = NULL;
1538 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1539 std::string unknown_action;
1540 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1541 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1542}
1543
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544// Test creating offers and receive answers and make sure the
1545// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001546TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001547 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001548 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001549 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550 const std::string session_id_orig = offer->session_id();
1551 const std::string session_version_orig = offer->session_version();
1552 SetLocalDescriptionWithoutError(offer);
1553
deadbeefab9b2d12015-10-14 11:33:11 -07001554 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001555 SessionDescriptionInterface* answer =
1556 CreateRemoteAnswer(session_->local_description());
1557 SetRemoteDescriptionWithoutError(answer);
1558
1559 video_channel_ = media_engine_->GetVideoChannel(0);
1560 voice_channel_ = media_engine_->GetVoiceChannel(0);
1561
1562 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1563 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1564
1565 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1566 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1567
1568 ASSERT_EQ(1u, video_channel_->send_streams().size());
1569 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1570 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1571 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1572
1573 // Create new offer without send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001574 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001575 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576
1577 // Verify the session id is the same and the session version is
1578 // increased.
1579 EXPECT_EQ(session_id_orig, offer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001580 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1581 rtc::FromString<uint64_t>(offer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582
1583 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001584 EXPECT_EQ(0u, video_channel_->send_streams().size());
1585 EXPECT_EQ(0u, voice_channel_->send_streams().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586
deadbeefab9b2d12015-10-14 11:33:11 -07001587 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 answer = CreateRemoteAnswer(session_->local_description());
1589 SetRemoteDescriptionWithoutError(answer);
1590
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 // Make sure the receive streams have not changed.
1592 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1593 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1594 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1595 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1596}
1597
1598// Test receiving offers and creating answers and make sure the
1599// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001600TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001601 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001602 SendAudioVideoStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001603 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001604 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605 SetRemoteDescriptionWithoutError(offer);
1606
deadbeefab9b2d12015-10-14 11:33:11 -07001607 SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001608 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001609 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 SetLocalDescriptionWithoutError(answer);
1611
1612 const std::string session_id_orig = answer->session_id();
1613 const std::string session_version_orig = answer->session_version();
1614
1615 video_channel_ = media_engine_->GetVideoChannel(0);
1616 voice_channel_ = media_engine_->GetVoiceChannel(0);
1617
1618 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1619 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1620
1621 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1622 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1623
1624 ASSERT_EQ(1u, video_channel_->send_streams().size());
1625 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1626 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1627 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1628
deadbeefab9b2d12015-10-14 11:33:11 -07001629 SendAudioVideoStream1And2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001630 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631 SetRemoteDescriptionWithoutError(offer);
1632
1633 // Answer by turning off all send streams.
deadbeefab9b2d12015-10-14 11:33:11 -07001634 SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001635 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636
1637 // Verify the session id is the same and the session version is
1638 // increased.
1639 EXPECT_EQ(session_id_orig, answer->session_id());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001640 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig),
1641 rtc::FromString<uint64_t>(answer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642 SetLocalDescriptionWithoutError(answer);
1643
1644 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1645 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1646 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1647 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1648 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1649 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1650
1651 // Make sure we have no send streams.
1652 EXPECT_EQ(0u, video_channel_->send_streams().size());
1653 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1654}
1655
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001656TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001657 Init();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001658 media_engine_->set_fail_create_channel(true);
1659
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001660 SessionDescriptionInterface* offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001661 ASSERT_TRUE(offer != NULL);
1662 // SetRemoteDescription and SetLocalDescription will take the ownership of
1663 // the offer.
1664 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001665 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001666 ASSERT_TRUE(offer != NULL);
1667 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1668}
1669
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001670//
1671// Tests for creating/setting SDP under different SDES/DTLS polices:
1672//
1673// --DTLS off and SDES on
1674// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1675// set local/remote offer/answer with crypto --> success
1676// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1677// failure
1678// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1679// failure
1680// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1681// failure
1682//
1683// --DTLS on and SDES off
1684// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1685// set local/remote offer/answer with DTLS fingerprint --> success
1686// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1687// fingerprint --> failure
1688// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1689// --> failure
1690// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1691// --> failure
1692//
1693// --Encryption disabled: DTLS off and SDES off
1694// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1695// answer without SDES or DTLS --> success
1696// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1697// answer without SDES or DTLS --> success
1698//
1699
1700// Test that we return a failure when applying a remote/local offer that doesn't
1701// have cryptos enabled when DTLS is off.
1702TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001703 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001705 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706 JsepSessionDescription* offer = CreateRemoteOffer(
1707 options, cricket::SEC_DISABLED);
1708 ASSERT_TRUE(offer != NULL);
1709 VerifyNoCryptoParams(offer->description(), false);
1710 // SetRemoteDescription and SetLocalDescription will take the ownership of
1711 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001712 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1714 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001715 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716}
1717
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001718// Test that we return a failure when applying a local answer that doesn't have
1719// cryptos enabled when DTLS is off.
1720TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001721 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722 SessionDescriptionInterface* offer = NULL;
1723 SessionDescriptionInterface* answer = NULL;
1724 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1725 // SetRemoteDescription and SetLocalDescription will take the ownership of
1726 // the offer.
1727 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001728 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729}
1730
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001731// Test we will return fail when apply an remote answer that doesn't have
1732// crypto enabled when DTLS is off.
1733TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001734 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001735 SessionDescriptionInterface* offer = NULL;
1736 SessionDescriptionInterface* answer = NULL;
1737 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1738 // SetRemoteDescription and SetLocalDescription will take the ownership of
1739 // the offer.
1740 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001741 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001742}
1743
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001744// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1745// and that we return an answer with a DTLS fingerprint.
Henrik Boström87713d02015-08-25 09:53:21 +02001746TEST_P(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001747 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefab9b2d12015-10-14 11:33:11 -07001748 SendAudioVideoStream1();
Henrik Boström87713d02015-08-25 09:53:21 +02001749 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 SetFactoryDtlsSrtp();
1751 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001752 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001753 JsepSessionDescription* offer =
1754 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755 ASSERT_TRUE(offer != NULL);
1756 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001757 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001758
1759 // SetRemoteDescription will take the ownership of the offer.
1760 SetRemoteDescriptionWithoutError(offer);
1761
1762 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001763 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764 ASSERT_TRUE(answer != NULL);
1765 VerifyFingerprintStatus(answer->description(), true);
1766 // Check that we don't have an a=crypto line in the answer.
1767 VerifyNoCryptoParams(answer->description(), true);
1768
1769 // Now set the local description, which should work, even without a=crypto.
1770 SetLocalDescriptionWithoutError(answer);
1771}
1772
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001773// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1774// and then we accept a remote answer with a DTLS fingerprint successfully.
Henrik Boström87713d02015-08-25 09:53:21 +02001775TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001776 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefab9b2d12015-10-14 11:33:11 -07001777 SendAudioVideoStream1();
Henrik Boström87713d02015-08-25 09:53:21 +02001778 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001779 SetFactoryDtlsSrtp();
1780
1781 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001782 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001783 ASSERT_TRUE(offer != NULL);
1784 VerifyFingerprintStatus(offer->description(), true);
1785 // Check that we don't have an a=crypto line in the offer.
1786 VerifyNoCryptoParams(offer->description(), true);
1787
1788 // Now set the local description, which should work, even without a=crypto.
1789 SetLocalDescriptionWithoutError(offer);
1790
1791 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001792 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001793 JsepSessionDescription* answer =
1794 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1795 ASSERT_TRUE(answer != NULL);
1796 VerifyFingerprintStatus(answer->description(), true);
1797 VerifyNoCryptoParams(answer->description(), true);
1798
1799 // SetRemoteDescription will take the ownership of the answer.
1800 SetRemoteDescriptionWithoutError(answer);
1801}
1802
1803// Test that if we support DTLS and the other side didn't offer a fingerprint,
1804// we will fail to set the remote description.
Henrik Boström87713d02015-08-25 09:53:21 +02001805TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001806 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001807 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001808 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001809 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001810 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811 JsepSessionDescription* offer = CreateRemoteOffer(
1812 options, cricket::SEC_REQUIRED);
1813 ASSERT_TRUE(offer != NULL);
1814 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001815 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001816
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001817 // SetRemoteDescription will take the ownership of the offer.
1818 SetRemoteDescriptionOfferExpectError(
1819 kSdpWithoutDtlsFingerprint, offer);
1820
1821 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1822 // SetLocalDescription will take the ownership of the offer.
1823 SetLocalDescriptionOfferExpectError(
1824 kSdpWithoutDtlsFingerprint, offer);
1825}
1826
1827// Test that we return a failure when applying a local answer that doesn't have
1828// a DTLS fingerprint when DTLS is required.
Henrik Boström87713d02015-08-25 09:53:21 +02001829TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001830 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001831 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001832 SessionDescriptionInterface* offer = NULL;
1833 SessionDescriptionInterface* answer = NULL;
1834 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1835
1836 // SetRemoteDescription and SetLocalDescription will take the ownership of
1837 // the offer and answer.
1838 SetRemoteDescriptionWithoutError(offer);
1839 SetLocalDescriptionAnswerExpectError(
1840 kSdpWithoutDtlsFingerprint, answer);
1841}
1842
1843// Test that we return a failure when applying a remote answer that doesn't have
1844// a DTLS fingerprint when DTLS is required.
Henrik Boström87713d02015-08-25 09:53:21 +02001845TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001846 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02001847 InitWithDtls(GetParam());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001848 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001849 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001850 options.recv_video = true;
deadbeefcbecd352015-09-23 11:50:27 -07001851 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer(
1852 CreateRemoteOffer(options, cricket::SEC_ENABLED));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001853 JsepSessionDescription* answer =
deadbeefcbecd352015-09-23 11:50:27 -07001854 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001855
1856 // SetRemoteDescription and SetLocalDescription will take the ownership of
1857 // the offer and answer.
1858 SetLocalDescriptionWithoutError(offer);
1859 SetRemoteDescriptionAnswerExpectError(
1860 kSdpWithoutDtlsFingerprint, answer);
1861}
1862
1863// Test that we create a local offer without SDES or DTLS and accept a remote
1864// answer without SDES or DTLS when encryption is disabled.
Henrik Boström87713d02015-08-25 09:53:21 +02001865TEST_P(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
deadbeefab9b2d12015-10-14 11:33:11 -07001866 SendAudioVideoStream1();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001867 options_.disable_encryption = true;
Henrik Boström87713d02015-08-25 09:53:21 +02001868 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001869
1870 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001871 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001872 ASSERT_TRUE(offer != NULL);
1873 VerifyFingerprintStatus(offer->description(), false);
1874 // Check that we don't have an a=crypto line in the offer.
1875 VerifyNoCryptoParams(offer->description(), false);
1876
1877 // Now set the local description, which should work, even without a=crypto.
1878 SetLocalDescriptionWithoutError(offer);
1879
1880 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001881 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001882 JsepSessionDescription* answer =
1883 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1884 ASSERT_TRUE(answer != NULL);
1885 VerifyFingerprintStatus(answer->description(), false);
1886 VerifyNoCryptoParams(answer->description(), false);
1887
1888 // SetRemoteDescription will take the ownership of the answer.
1889 SetRemoteDescriptionWithoutError(answer);
1890}
1891
1892// Test that we create a local answer without SDES or DTLS and accept a remote
1893// offer without SDES or DTLS when encryption is disabled.
Henrik Boström87713d02015-08-25 09:53:21 +02001894TEST_P(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001895 options_.disable_encryption = true;
Henrik Boström87713d02015-08-25 09:53:21 +02001896 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001897
1898 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001899 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001900 JsepSessionDescription* offer =
1901 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1902 ASSERT_TRUE(offer != NULL);
1903 VerifyFingerprintStatus(offer->description(), false);
1904 VerifyNoCryptoParams(offer->description(), false);
1905
1906 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907 SetRemoteDescriptionWithoutError(offer);
1908
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001909 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001910 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001911 ASSERT_TRUE(answer != NULL);
1912 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001913 // Check that we don't have an a=crypto line in the answer.
1914 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001916 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 SetLocalDescriptionWithoutError(answer);
1918}
1919
1920TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001921 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001922 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001924 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001925 SetLocalDescriptionWithoutError(offer);
1926
1927 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001928 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001929 SetLocalDescriptionWithoutError(offer2);
1930}
1931
1932TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001933 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001934 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001935 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001936 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001937 SetRemoteDescriptionWithoutError(offer);
1938
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001939 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940 SetRemoteDescriptionWithoutError(offer2);
1941}
1942
1943TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001944 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001945 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001946 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001947 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001948 offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001949 SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER",
1950 offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001951}
1952
1953TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001954 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001955 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001956 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957 SetRemoteDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001958 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001959 SetLocalDescriptionOfferExpectError(
deadbeefd59daf82015-10-14 15:02:44 -07001960 "Called in wrong state: STATE_RECEIVEDOFFER", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961}
1962
1963TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001964 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001965 SendNothing();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001966 SessionDescriptionInterface* offer = CreateRemoteOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001967 SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001968
1969 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001970 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001971 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
deadbeefd59daf82015-10-14 15:02:44 -07001972 SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001973
deadbeefab9b2d12015-10-14 11:33:11 -07001974 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001975 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001976 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001977 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1978
deadbeefd59daf82015-10-14 15:02:44 -07001979 SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980
deadbeefab9b2d12015-10-14 11:33:11 -07001981 SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001982 SessionDescriptionInterface* answer = CreateAnswer(NULL);
deadbeefd59daf82015-10-14 15:02:44 -07001983 SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001984}
1985
1986TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00001987 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07001988 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001989 SessionDescriptionInterface* offer = CreateOffer();
deadbeefd59daf82015-10-14 15:02:44 -07001990 SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991
1992 JsepSessionDescription* pranswer =
1993 CreateRemoteAnswer(session_->local_description());
1994 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1995
1996 SetRemoteDescriptionExpectState(pranswer,
deadbeefd59daf82015-10-14 15:02:44 -07001997 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998
deadbeefab9b2d12015-10-14 11:33:11 -07001999 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 JsepSessionDescription* pranswer2 =
2001 CreateRemoteAnswer(session_->local_description());
2002 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
2003
2004 SetRemoteDescriptionExpectState(pranswer2,
deadbeefd59daf82015-10-14 15:02:44 -07002005 WebRtcSession::STATE_RECEIVEDPRANSWER);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002006
deadbeefab9b2d12015-10-14 11:33:11 -07002007 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002008 SessionDescriptionInterface* answer =
2009 CreateRemoteAnswer(session_->local_description());
deadbeefd59daf82015-10-14 15:02:44 -07002010 SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011}
2012
2013TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002014 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002015 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002016 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2017
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018 SessionDescriptionInterface* answer =
2019 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002020 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
2021 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022}
2023
2024TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002025 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002026 SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002027 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2028
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 SessionDescriptionInterface* answer =
2030 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002031 SetRemoteDescriptionAnswerExpectError(
2032 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033}
2034
2035TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002036 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002037 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038
2039 cricket::Candidate candidate;
2040 candidate.set_component(1);
2041 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
2042
deadbeefd59daf82015-10-14 15:02:44 -07002043 // Fail since we have not set a remote description.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002044 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
2045
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002046 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002047 SetLocalDescriptionWithoutError(offer);
deadbeefd59daf82015-10-14 15:02:44 -07002048
2049 // Fail since we have not set a remote description.
2050 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002051
2052 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2053 session_->local_description());
2054 SetRemoteDescriptionWithoutError(answer);
2055
deadbeefd59daf82015-10-14 15:02:44 -07002056 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2057 candidate.set_component(2);
2058 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
2059 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2060
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061 // Verifying the candidates are copied properly from internal vector.
2062 const SessionDescriptionInterface* remote_desc =
2063 session_->remote_description();
2064 ASSERT_TRUE(remote_desc != NULL);
2065 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2066 const IceCandidateCollection* candidates =
2067 remote_desc->candidates(kMediaContentIndex0);
2068 ASSERT_EQ(2u, candidates->count());
2069 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2070 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
2071 EXPECT_EQ(1, candidates->at(0)->candidate().component());
2072 EXPECT_EQ(2, candidates->at(1)->candidate().component());
2073
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002074 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
2075 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002076 candidate.set_component(2);
2077 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
2078 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00002079 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002080
2081 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
2082 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
2083}
2084
2085// Test that a remote candidate is added to the remote session description and
2086// that it is retained if the remote session description is changed.
2087TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002088 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 cricket::Candidate candidate1;
2090 candidate1.set_component(1);
2091 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
2092 candidate1);
deadbeefab9b2d12015-10-14 11:33:11 -07002093 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002094 CreateAndSetRemoteOfferAndLocalAnswer();
2095
2096 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2097 const SessionDescriptionInterface* remote_desc =
2098 session_->remote_description();
2099 ASSERT_TRUE(remote_desc != NULL);
2100 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2101 const IceCandidateCollection* candidates =
2102 remote_desc->candidates(kMediaContentIndex0);
2103 ASSERT_EQ(1u, candidates->count());
2104 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2105
2106 // Update the RemoteSessionDescription with a new session description and
2107 // a candidate and check that the new remote session description contains both
2108 // candidates.
2109 SessionDescriptionInterface* offer = CreateRemoteOffer();
2110 cricket::Candidate candidate2;
2111 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2112 candidate2);
2113 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
2114 SetRemoteDescriptionWithoutError(offer);
2115
2116 remote_desc = session_->remote_description();
2117 ASSERT_TRUE(remote_desc != NULL);
2118 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2119 candidates = remote_desc->candidates(kMediaContentIndex0);
2120 ASSERT_EQ(2u, candidates->count());
2121 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2122 // Username and password have be updated with the TransportInfo of the
2123 // SessionDescription, won't be equal to the original one.
2124 candidate2.set_username(candidates->at(0)->candidate().username());
2125 candidate2.set_password(candidates->at(0)->candidate().password());
2126 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
2127 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
2128 // No need to verify the username and password.
2129 candidate1.set_username(candidates->at(1)->candidate().username());
2130 candidate1.set_password(candidates->at(1)->candidate().password());
2131 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
2132
2133 // Test that the candidate is ignored if we can add the same candidate again.
2134 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2135}
2136
2137// Test that local candidates are added to the local session description and
2138// that they are retained if the local session description is changed.
2139TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002140 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002141 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002142 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002143 CreateAndSetRemoteOfferAndLocalAnswer();
2144
2145 const SessionDescriptionInterface* local_desc = session_->local_description();
2146 const IceCandidateCollection* candidates =
2147 local_desc->candidates(kMediaContentIndex0);
2148 ASSERT_TRUE(candidates != NULL);
2149 EXPECT_EQ(0u, candidates->count());
2150
2151 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2152
2153 local_desc = session_->local_description();
2154 candidates = local_desc->candidates(kMediaContentIndex0);
2155 ASSERT_TRUE(candidates != NULL);
2156 EXPECT_LT(0u, candidates->count());
2157 candidates = local_desc->candidates(1);
2158 ASSERT_TRUE(candidates != NULL);
deadbeefcbecd352015-09-23 11:50:27 -07002159 EXPECT_EQ(0u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002160
2161 // Update the session descriptions.
deadbeefab9b2d12015-10-14 11:33:11 -07002162 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 CreateAndSetRemoteOfferAndLocalAnswer();
2164
2165 local_desc = session_->local_description();
2166 candidates = local_desc->candidates(kMediaContentIndex0);
2167 ASSERT_TRUE(candidates != NULL);
2168 EXPECT_LT(0u, candidates->count());
2169 candidates = local_desc->candidates(1);
2170 ASSERT_TRUE(candidates != NULL);
deadbeefcbecd352015-09-23 11:50:27 -07002171 EXPECT_EQ(0u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002172}
2173
2174// Test that we can set a remote session description with remote candidates.
2175TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002176 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002177
2178 cricket::Candidate candidate1;
2179 candidate1.set_component(1);
2180 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2181 candidate1);
deadbeefab9b2d12015-10-14 11:33:11 -07002182 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002183 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002184
2185 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2186 SetRemoteDescriptionWithoutError(offer);
2187
2188 const SessionDescriptionInterface* remote_desc =
2189 session_->remote_description();
2190 ASSERT_TRUE(remote_desc != NULL);
2191 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
2192 const IceCandidateCollection* candidates =
2193 remote_desc->candidates(kMediaContentIndex0);
2194 ASSERT_EQ(1u, candidates->count());
2195 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2196
wu@webrtc.org91053e72013-08-10 07:18:04 +00002197 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198 SetLocalDescriptionWithoutError(answer);
2199}
2200
2201// Test that offers and answers contains ice candidates when Ice candidates have
2202// been gathered.
2203TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002204 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002205 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002206 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 // Ice is started but candidates are not provided until SetLocalDescription
2208 // is called.
2209 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
2210 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
2211 CreateAndSetRemoteOfferAndLocalAnswer();
2212 // Wait until at least one local candidate has been collected.
2213 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
2214 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002215
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002216 rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
2217
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
2219 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002220
2221 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
2222 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002223 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002224 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
2225 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 SetLocalDescriptionWithoutError(answer);
2227}
2228
2229// Verifies TransportProxy and media channels are created with content names
2230// present in the SessionDescription.
2231TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002232 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002233 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002234 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235
2236 // CreateOffer creates session description with the content names "audio" and
deadbeefd59daf82015-10-14 15:02:44 -07002237 // "video". Goal is to modify these content names and verify transport
2238 // channels
2239 // in the WebRtcSession, as channels are created with the content names
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002240 // present in SDP.
2241 std::string sdp;
2242 EXPECT_TRUE(offer->ToString(&sdp));
2243 const std::string kAudioMid = "a=mid:audio";
2244 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2245 const std::string kVideoMid = "a=mid:video";
2246 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
2247
2248 // Replacing |audio| with |audio_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002249 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 kAudioMidReplaceStr.c_str(),
2251 kAudioMidReplaceStr.length(),
2252 &sdp);
2253 // Replacing |video| with |video_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002254 rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002255 kVideoMidReplaceStr.c_str(),
2256 kVideoMidReplaceStr.length(),
2257 &sdp);
2258
2259 SessionDescriptionInterface* modified_offer =
2260 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2261
2262 SetRemoteDescriptionWithoutError(modified_offer);
2263
2264 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00002265 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266 SetLocalDescriptionWithoutError(answer);
2267
deadbeefcbecd352015-09-23 11:50:27 -07002268 cricket::TransportChannel* voice_transport_channel =
2269 session_->voice_rtp_transport_channel();
2270 EXPECT_TRUE(voice_transport_channel != NULL);
2271 EXPECT_EQ(voice_transport_channel->transport_name(), "audio_content_name");
2272 cricket::TransportChannel* video_transport_channel =
2273 session_->video_rtp_transport_channel();
2274 EXPECT_TRUE(video_transport_channel != NULL);
2275 EXPECT_EQ(video_transport_channel->transport_name(), "video_content_name");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
2277 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
2278}
2279
2280// Test that an offer contains the correct media content descriptions based on
2281// the send streams when no constraints have been set.
2282TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002283 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002284 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2285
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002286 ASSERT_TRUE(offer != NULL);
2287 const cricket::ContentInfo* content =
2288 cricket::GetFirstAudioContent(offer->description());
2289 EXPECT_TRUE(content != NULL);
2290 content = cricket::GetFirstVideoContent(offer->description());
2291 EXPECT_TRUE(content == NULL);
2292}
2293
2294// Test that an offer contains the correct media content descriptions based on
2295// the send streams when no constraints have been set.
2296TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002297 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002298 // Test Audio only offer.
deadbeefab9b2d12015-10-14 11:33:11 -07002299 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002300 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2301
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002302 const cricket::ContentInfo* content =
2303 cricket::GetFirstAudioContent(offer->description());
2304 EXPECT_TRUE(content != NULL);
2305 content = cricket::GetFirstVideoContent(offer->description());
2306 EXPECT_TRUE(content == NULL);
2307
2308 // Test Audio / Video offer.
deadbeefab9b2d12015-10-14 11:33:11 -07002309 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002310 offer.reset(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002311 content = cricket::GetFirstAudioContent(offer->description());
2312 EXPECT_TRUE(content != NULL);
2313 content = cricket::GetFirstVideoContent(offer->description());
2314 EXPECT_TRUE(content != NULL);
2315}
2316
2317// Test that an offer contains no media content descriptions if
2318// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
2319TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002320 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002321 PeerConnectionInterface::RTCOfferAnswerOptions options;
2322 options.offer_to_receive_audio = 0;
2323 options.offer_to_receive_video = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002324
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002325 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002326 CreateOffer(options));
2327
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002328 ASSERT_TRUE(offer != NULL);
2329 const cricket::ContentInfo* content =
2330 cricket::GetFirstAudioContent(offer->description());
2331 EXPECT_TRUE(content == NULL);
2332 content = cricket::GetFirstVideoContent(offer->description());
2333 EXPECT_TRUE(content == NULL);
2334}
2335
2336// Test that an offer contains only audio media content descriptions if
2337// kOfferToReceiveAudio constraints are set to true.
2338TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002339 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002340 PeerConnectionInterface::RTCOfferAnswerOptions options;
2341 options.offer_to_receive_audio =
2342 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2343
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002344 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002345 CreateOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346
2347 const cricket::ContentInfo* content =
2348 cricket::GetFirstAudioContent(offer->description());
2349 EXPECT_TRUE(content != NULL);
2350 content = cricket::GetFirstVideoContent(offer->description());
2351 EXPECT_TRUE(content == NULL);
2352}
2353
2354// Test that an offer contains audio and video media content descriptions if
2355// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
2356TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002357 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002358 // Test Audio / Video offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002359 PeerConnectionInterface::RTCOfferAnswerOptions options;
2360 options.offer_to_receive_audio =
2361 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2362 options.offer_to_receive_video =
2363 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2364
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002365 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002366 CreateOffer(options));
2367
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002368 const cricket::ContentInfo* content =
2369 cricket::GetFirstAudioContent(offer->description());
jiayl@webrtc.orgc1723202014-09-08 20:44:36 +00002370 EXPECT_TRUE(content != NULL);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002371
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372 content = cricket::GetFirstVideoContent(offer->description());
2373 EXPECT_TRUE(content != NULL);
2374
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002375 // Sets constraints to false and verifies that audio/video contents are
2376 // removed.
2377 options.offer_to_receive_audio = 0;
2378 options.offer_to_receive_video = 0;
2379 offer.reset(CreateOffer(options));
2380
2381 content = cricket::GetFirstAudioContent(offer->description());
2382 EXPECT_TRUE(content == NULL);
2383 content = cricket::GetFirstVideoContent(offer->description());
2384 EXPECT_TRUE(content == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002385}
2386
2387// Test that an answer can not be created if the last remote description is not
2388// an offer.
2389TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002390 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002391 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002392 SetLocalDescriptionWithoutError(offer);
2393 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2394 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002395 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396}
2397
2398// Test that an answer contains the correct media content descriptions when no
2399// constraints have been set.
2400TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002401 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002402 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002403 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002404 SetRemoteDescriptionWithoutError(offer.release());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002405 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002406 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002407 const cricket::ContentInfo* content =
2408 cricket::GetFirstAudioContent(answer->description());
2409 ASSERT_TRUE(content != NULL);
2410 EXPECT_FALSE(content->rejected);
2411
2412 content = cricket::GetFirstVideoContent(answer->description());
2413 ASSERT_TRUE(content != NULL);
2414 EXPECT_FALSE(content->rejected);
2415}
2416
2417// Test that an answer contains the correct media content descriptions when no
2418// constraints have been set and the offer only contain audio.
2419TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002420 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002421 // Create a remote offer with audio only.
2422 cricket::MediaSessionOptions options;
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002423
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002424 rtc::scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002425 CreateRemoteOffer(options));
2426 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
2427 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
2428
2429 SetRemoteDescriptionWithoutError(offer.release());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002430 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002431 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002432 const cricket::ContentInfo* content =
2433 cricket::GetFirstAudioContent(answer->description());
2434 ASSERT_TRUE(content != NULL);
2435 EXPECT_FALSE(content->rejected);
2436
2437 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
2438}
2439
2440// Test that an answer contains the correct media content descriptions when no
2441// constraints have been set.
2442TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002443 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002444 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002445 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002446 SetRemoteDescriptionWithoutError(offer.release());
2447 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07002448 SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002449 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002450 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002451 const cricket::ContentInfo* content =
2452 cricket::GetFirstAudioContent(answer->description());
2453 ASSERT_TRUE(content != NULL);
2454 EXPECT_FALSE(content->rejected);
2455
2456 content = cricket::GetFirstVideoContent(answer->description());
2457 ASSERT_TRUE(content != NULL);
2458 EXPECT_FALSE(content->rejected);
2459}
2460
2461// Test that an answer contains the correct media content descriptions when
2462// constraints have been set but no stream is sent.
2463TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002464 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002465 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002466 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002467 SetRemoteDescriptionWithoutError(offer.release());
2468
2469 webrtc::FakeConstraints constraints_no_receive;
2470 constraints_no_receive.SetMandatoryReceiveAudio(false);
2471 constraints_no_receive.SetMandatoryReceiveVideo(false);
2472
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002473 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002474 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002475 const cricket::ContentInfo* content =
2476 cricket::GetFirstAudioContent(answer->description());
2477 ASSERT_TRUE(content != NULL);
2478 EXPECT_TRUE(content->rejected);
2479
2480 content = cricket::GetFirstVideoContent(answer->description());
2481 ASSERT_TRUE(content != NULL);
2482 EXPECT_TRUE(content->rejected);
2483}
2484
2485// Test that an answer contains the correct media content descriptions when
2486// constraints have been set and streams are sent.
2487TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002488 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002489 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002490 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002491 SetRemoteDescriptionWithoutError(offer.release());
2492
2493 webrtc::FakeConstraints constraints_no_receive;
2494 constraints_no_receive.SetMandatoryReceiveAudio(false);
2495 constraints_no_receive.SetMandatoryReceiveVideo(false);
2496
2497 // Test with a stream with tracks.
deadbeefab9b2d12015-10-14 11:33:11 -07002498 SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002499 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002500 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002501
2502 // TODO(perkj): Should the direction be set to SEND_ONLY?
2503 const cricket::ContentInfo* content =
2504 cricket::GetFirstAudioContent(answer->description());
2505 ASSERT_TRUE(content != NULL);
2506 EXPECT_FALSE(content->rejected);
2507
2508 // TODO(perkj): Should the direction be set to SEND_ONLY?
2509 content = cricket::GetFirstVideoContent(answer->description());
2510 ASSERT_TRUE(content != NULL);
2511 EXPECT_FALSE(content->rejected);
2512}
2513
2514TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2515 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002516 Init();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002517 PeerConnectionInterface::RTCOfferAnswerOptions options;
2518 options.offer_to_receive_audio =
2519 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2520 options.voice_activity_detection = false;
2521
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002522 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002523 CreateOffer(options));
2524
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002525 const cricket::ContentInfo* content =
2526 cricket::GetFirstAudioContent(offer->description());
2527 EXPECT_TRUE(content != NULL);
2528 EXPECT_TRUE(VerifyNoCNCodecs(content));
2529}
2530
2531TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2532 AddCNCodecs();
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002533 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002534 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002535 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002536 SetRemoteDescriptionWithoutError(offer.release());
2537
2538 webrtc::FakeConstraints constraints;
2539 constraints.SetOptionalVAD(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002540 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002541 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002542 const cricket::ContentInfo* content =
2543 cricket::GetFirstAudioContent(answer->description());
2544 ASSERT_TRUE(content != NULL);
2545 EXPECT_TRUE(VerifyNoCNCodecs(content));
2546}
2547
2548// This test verifies the call setup when remote answer with audio only and
2549// later updates with video.
2550TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002551 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002552 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2553 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2554
deadbeefab9b2d12015-10-14 11:33:11 -07002555 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002556 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002557
2558 cricket::MediaSessionOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002559 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2560
2561 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2562 // and answer;
2563 SetLocalDescriptionWithoutError(offer);
2564 SetRemoteDescriptionWithoutError(answer);
2565
2566 video_channel_ = media_engine_->GetVideoChannel(0);
2567 voice_channel_ = media_engine_->GetVoiceChannel(0);
2568
2569 ASSERT_TRUE(video_channel_ == NULL);
2570
2571 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2572 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2573 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2574
2575 // Let the remote end update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002576 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002577 CreateAndSetRemoteOfferAndLocalAnswer();
2578
2579 video_channel_ = media_engine_->GetVideoChannel(0);
2580 voice_channel_ = media_engine_->GetVoiceChannel(0);
2581
2582 ASSERT_TRUE(video_channel_ != NULL);
2583 ASSERT_TRUE(voice_channel_ != NULL);
2584
2585 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2586 ASSERT_EQ(1u, video_channel_->send_streams().size());
2587 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2588 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2589 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2590 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2591 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2592 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2593
2594 // Change session back to audio only.
deadbeefab9b2d12015-10-14 11:33:11 -07002595 SendAudioOnlyStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002596 CreateAndSetRemoteOfferAndLocalAnswer();
2597
2598 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2599 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2600 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2601 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2602 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2603}
2604
2605// This test verifies the call setup when remote answer with video only and
2606// later updates with audio.
2607TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002608 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002609 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2610 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
deadbeefab9b2d12015-10-14 11:33:11 -07002611 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002612 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002613
2614 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002615 options.recv_audio = false;
2616 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002617 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2618 offer, options, cricket::SEC_ENABLED);
2619
2620 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2621 // and answer.
2622 SetLocalDescriptionWithoutError(offer);
2623 SetRemoteDescriptionWithoutError(answer);
2624
2625 video_channel_ = media_engine_->GetVideoChannel(0);
2626 voice_channel_ = media_engine_->GetVoiceChannel(0);
2627
2628 ASSERT_TRUE(voice_channel_ == NULL);
2629 ASSERT_TRUE(video_channel_ != NULL);
2630
2631 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2632 ASSERT_EQ(1u, video_channel_->send_streams().size());
2633 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2634
2635 // Update the session descriptions, with Audio and Video.
deadbeefab9b2d12015-10-14 11:33:11 -07002636 SendAudioVideoStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002637 CreateAndSetRemoteOfferAndLocalAnswer();
2638
2639 voice_channel_ = media_engine_->GetVoiceChannel(0);
2640 ASSERT_TRUE(voice_channel_ != NULL);
2641
2642 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2643 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2644 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2645 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2646
2647 // Change session back to video only.
deadbeefab9b2d12015-10-14 11:33:11 -07002648 SendVideoOnlyStream2();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002649 CreateAndSetRemoteOfferAndLocalAnswer();
2650
2651 video_channel_ = media_engine_->GetVideoChannel(0);
2652 voice_channel_ = media_engine_->GetVoiceChannel(0);
2653
2654 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2655 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2656 ASSERT_EQ(1u, video_channel_->send_streams().size());
2657 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2658}
2659
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002660TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002661 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002662 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002663 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002664 VerifyCryptoParams(offer->description());
2665 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002666 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002667 VerifyCryptoParams(answer->description());
2668}
2669
2670TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002671 options_.disable_encryption = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002672 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002673 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002674 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002675 VerifyNoCryptoParams(offer->description(), false);
2676}
2677
2678TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002679 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002680 VerifyAnswerFromNonCryptoOffer();
2681}
2682
2683TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002684 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002685 VerifyAnswerFromCryptoOffer();
2686}
2687
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002688// This test verifies that setLocalDescription fails if
2689// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2690TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002691 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002692 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002693 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2694
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002695 std::string sdp;
2696 RemoveIceUfragPwdLines(offer.get(), &sdp);
2697 SessionDescriptionInterface* modified_offer =
2698 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002699 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002700}
2701
2702// This test verifies that setRemoteDescription fails if
2703// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2704TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002705 Init();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002706 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002707 std::string sdp;
2708 RemoveIceUfragPwdLines(offer.get(), &sdp);
2709 SessionDescriptionInterface* modified_offer =
2710 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002711 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002712}
2713
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002714// This test verifies that setLocalDescription fails if local offer has
2715// too short ice ufrag and pwd strings.
2716TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002717 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07002718 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002719 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2720
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002721 std::string sdp;
2722 // Modifying ice ufrag and pwd in local offer with strings smaller than the
2723 // recommended values of 4 and 22 bytes respectively.
2724 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2725 SessionDescriptionInterface* modified_offer =
2726 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2727 std::string error;
2728 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2729
2730 // Test with string greater than 256.
2731 sdp.clear();
2732 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2733 &sdp);
2734 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2735 NULL);
2736 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2737}
2738
2739// This test verifies that setRemoteDescription fails if remote offer has
2740// too short ice ufrag and pwd strings.
2741TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00002742 Init();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002743 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002744 std::string sdp;
2745 // Modifying ice ufrag and pwd in remote offer with strings smaller than the
2746 // recommended values of 4 and 22 bytes respectively.
2747 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2748 SessionDescriptionInterface* modified_offer =
2749 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2750 std::string error;
2751 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2752
2753 sdp.clear();
2754 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2755 &sdp);
2756 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2757 NULL);
2758 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2759}
2760
honghaiz503726c2015-07-31 12:37:38 -07002761// Test that if the remote description indicates the peer requested ICE restart
2762// (via a new ufrag or pwd), the old ICE candidates are not copied,
2763// and vice versa.
2764TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithIceRestart) {
2765 Init();
2766 scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2767
2768 // Create the first offer.
2769 std::string sdp;
2770 ModifyIceUfragPwdLines(offer.get(), "0123456789012345",
2771 "abcdefghijklmnopqrstuvwx", &sdp);
2772 SessionDescriptionInterface* offer1 =
2773 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2774 cricket::Candidate candidate1(1, "udp", rtc::SocketAddress("1.1.1.1", 5000),
2775 0, "", "", "relay", 0, "");
2776 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
2777 candidate1);
2778 EXPECT_TRUE(offer1->AddCandidate(&ice_candidate1));
2779 SetRemoteDescriptionWithoutError(offer1);
2780 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2781
2782 // The second offer has the same ufrag and pwd but different address.
2783 sdp.clear();
2784 ModifyIceUfragPwdLines(offer.get(), "0123456789012345",
2785 "abcdefghijklmnopqrstuvwx", &sdp);
2786 SessionDescriptionInterface* offer2 =
2787 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2788 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
2789 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2790 candidate1);
2791 EXPECT_TRUE(offer2->AddCandidate(&ice_candidate2));
2792 SetRemoteDescriptionWithoutError(offer2);
2793 EXPECT_EQ(2, session_->remote_description()->candidates(0)->count());
2794
2795 // The third offer has a different ufrag and different address.
2796 sdp.clear();
2797 ModifyIceUfragPwdLines(offer.get(), "0123456789012333",
2798 "abcdefghijklmnopqrstuvwx", &sdp);
2799 SessionDescriptionInterface* offer3 =
2800 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2801 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 7000));
2802 JsepIceCandidate ice_candidate3(kMediaContentName0, kMediaContentIndex0,
2803 candidate1);
2804 EXPECT_TRUE(offer3->AddCandidate(&ice_candidate3));
2805 SetRemoteDescriptionWithoutError(offer3);
2806 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count());
2807
2808 // The fourth offer has no candidate but a different ufrag/pwd.
2809 sdp.clear();
2810 ModifyIceUfragPwdLines(offer.get(), "0123456789012444",
2811 "abcdefghijklmnopqrstuvyz", &sdp);
2812 SessionDescriptionInterface* offer4 =
2813 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2814 SetRemoteDescriptionWithoutError(offer4);
2815 EXPECT_EQ(0, session_->remote_description()->candidates(0)->count());
2816}
2817
Donald Curtisd4f769d2015-05-28 09:48:21 -07002818// Test that candidates sent to the "video" transport do not get pushed down to
deadbeefd59daf82015-10-14 15:02:44 -07002819// the "audio" transport channel when bundling.
Donald Curtisd4f769d2015-05-28 09:48:21 -07002820TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
2821 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
2822
2823 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002824 SendAudioVideoStream1();
Donald Curtisd4f769d2015-05-28 09:48:21 -07002825
2826 PeerConnectionInterface::RTCOfferAnswerOptions options;
2827 options.use_rtp_mux = true;
2828
2829 SessionDescriptionInterface* offer = CreateRemoteOffer();
2830 SetRemoteDescriptionWithoutError(offer);
2831
2832 SessionDescriptionInterface* answer = CreateAnswer(NULL);
2833 SetLocalDescriptionWithoutError(answer);
2834
deadbeefcbecd352015-09-23 11:50:27 -07002835 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2836 session_->video_rtp_transport_channel());
Donald Curtisd4f769d2015-05-28 09:48:21 -07002837
deadbeefcbecd352015-09-23 11:50:27 -07002838 cricket::BaseChannel* voice_channel = session_->voice_channel();
2839 ASSERT(voice_channel != NULL);
Donald Curtisd4f769d2015-05-28 09:48:21 -07002840
2841 // Checks if one of the transport channels contains a connection using a given
2842 // port.
deadbeefcbecd352015-09-23 11:50:27 -07002843 auto connection_with_remote_port = [this, voice_channel](int port) {
deadbeefd59daf82015-10-14 15:02:44 -07002844 SessionStats stats;
deadbeefcbecd352015-09-23 11:50:27 -07002845 session_->GetChannelTransportStats(voice_channel, &stats);
2846 for (auto& kv : stats.transport_stats) {
2847 for (auto& chan_stat : kv.second.channel_stats) {
2848 for (auto& conn_info : chan_stat.connection_infos) {
2849 if (conn_info.remote_candidate.address().port() == port) {
2850 return true;
2851 }
Donald Curtisd4f769d2015-05-28 09:48:21 -07002852 }
2853 }
2854 }
2855 return false;
2856 };
2857
2858 EXPECT_FALSE(connection_with_remote_port(5000));
2859 EXPECT_FALSE(connection_with_remote_port(5001));
2860 EXPECT_FALSE(connection_with_remote_port(6000));
2861
2862 // The way the *_WAIT checks work is they only wait if the condition fails,
2863 // which does not help in the case where state is not changing. This is
2864 // problematic in this test since we want to verify that adding a video
2865 // candidate does _not_ change state. So we interleave candidates and assume
2866 // that messages are executed in the order they were posted.
2867
2868 // First audio candidate.
2869 cricket::Candidate candidate0;
2870 candidate0.set_address(rtc::SocketAddress("1.1.1.1", 5000));
2871 candidate0.set_component(1);
2872 candidate0.set_protocol("udp");
2873 JsepIceCandidate ice_candidate0(kMediaContentName0, kMediaContentIndex0,
2874 candidate0);
2875 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate0));
2876
2877 // Video candidate.
2878 cricket::Candidate candidate1;
2879 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000));
2880 candidate1.set_component(1);
2881 candidate1.set_protocol("udp");
2882 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2883 candidate1);
2884 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
2885
2886 // Second audio candidate.
2887 cricket::Candidate candidate2;
2888 candidate2.set_address(rtc::SocketAddress("1.1.1.1", 5001));
2889 candidate2.set_component(1);
2890 candidate2.set_protocol("udp");
2891 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
2892 candidate2);
2893 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
2894
2895 EXPECT_TRUE_WAIT(connection_with_remote_port(5000), 1000);
2896 EXPECT_TRUE_WAIT(connection_with_remote_port(5001), 1000);
2897
2898 // No need here for a _WAIT check since we are checking that state hasn't
2899 // changed: if this is false we would be doing waits for nothing and if this
2900 // is true then there will be no messages processed anyways.
2901 EXPECT_FALSE(connection_with_remote_port(6000));
2902}
2903
deadbeefcbecd352015-09-23 11:50:27 -07002904// kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07002905TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) {
2906 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002907 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002908
2909 PeerConnectionInterface::RTCOfferAnswerOptions options;
2910 options.use_rtp_mux = true;
2911
2912 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002913 SetLocalDescriptionWithoutError(offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07002914
deadbeefcbecd352015-09-23 11:50:27 -07002915 EXPECT_NE(session_->voice_rtp_transport_channel(),
2916 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002917
deadbeefab9b2d12015-10-14 11:33:11 -07002918 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002919 SessionDescriptionInterface* answer =
2920 CreateRemoteAnswer(session_->local_description());
2921 SetRemoteDescriptionWithoutError(answer);
2922
deadbeefcbecd352015-09-23 11:50:27 -07002923 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2924 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002925}
2926
deadbeefcbecd352015-09-23 11:50:27 -07002927// kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07002928TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) {
2929 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07002930 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07002931
Donald Curtis0e209b02015-03-24 09:29:54 -07002932 PeerConnectionInterface::RTCOfferAnswerOptions options;
2933 options.use_rtp_mux = true;
2934
2935 SessionDescriptionInterface* offer = CreateOffer(options);
2936 SetLocalDescriptionWithoutError(offer);
2937
deadbeefcbecd352015-09-23 11:50:27 -07002938 EXPECT_NE(session_->voice_rtp_transport_channel(),
2939 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002940
deadbeefab9b2d12015-10-14 11:33:11 -07002941 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002942
2943 // Remove BUNDLE from the answer.
2944 rtc::scoped_ptr<SessionDescriptionInterface> answer(
2945 CreateRemoteAnswer(session_->local_description()));
2946 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2947 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2948 JsepSessionDescription* modified_answer =
2949 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2950 modified_answer->Initialize(answer_copy, "1", "1");
2951 SetRemoteDescriptionWithoutError(modified_answer); //
2952
deadbeefcbecd352015-09-23 11:50:27 -07002953 EXPECT_NE(session_->voice_rtp_transport_channel(),
2954 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002955}
2956
2957// kBundlePolicyMaxBundle policy with BUNDLE in the answer.
2958TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) {
2959 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002960 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07002961
2962 PeerConnectionInterface::RTCOfferAnswerOptions options;
2963 options.use_rtp_mux = true;
2964
2965 SessionDescriptionInterface* offer = CreateOffer(options);
2966 SetLocalDescriptionWithoutError(offer);
2967
deadbeefcbecd352015-09-23 11:50:27 -07002968 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2969 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07002970
deadbeefab9b2d12015-10-14 11:33:11 -07002971 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07002972 SessionDescriptionInterface* answer =
2973 CreateRemoteAnswer(session_->local_description());
2974 SetRemoteDescriptionWithoutError(answer);
2975
deadbeefcbecd352015-09-23 11:50:27 -07002976 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2977 session_->video_rtp_transport_channel());
2978}
2979
2980// kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no
2981// audio content in the answer.
2982TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) {
2983 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07002984 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07002985
2986 PeerConnectionInterface::RTCOfferAnswerOptions options;
2987 options.use_rtp_mux = true;
2988
2989 SessionDescriptionInterface* offer = CreateOffer(options);
2990 SetLocalDescriptionWithoutError(offer);
2991
2992 EXPECT_EQ(session_->voice_rtp_transport_channel(),
2993 session_->video_rtp_transport_channel());
2994
deadbeefab9b2d12015-10-14 11:33:11 -07002995 SendAudioVideoStream2();
deadbeefcbecd352015-09-23 11:50:27 -07002996 cricket::MediaSessionOptions recv_options;
2997 recv_options.recv_audio = false;
2998 recv_options.recv_video = true;
2999 SessionDescriptionInterface* answer =
3000 CreateRemoteAnswer(session_->local_description(), recv_options);
3001 SetRemoteDescriptionWithoutError(answer);
3002
deadbeefd59daf82015-10-14 15:02:44 -07003003 EXPECT_TRUE(nullptr == session_->voice_channel());
3004 EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
deadbeefcbecd352015-09-23 11:50:27 -07003005
deadbeefd59daf82015-10-14 15:02:44 -07003006 session_->Close();
3007 EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
3008 EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
3009 EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
3010 EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003011}
3012
3013// kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
3014TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) {
3015 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003016 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07003017
Donald Curtis0e209b02015-03-24 09:29:54 -07003018 PeerConnectionInterface::RTCOfferAnswerOptions options;
3019 options.use_rtp_mux = true;
3020
3021 SessionDescriptionInterface* offer = CreateOffer(options);
3022 SetLocalDescriptionWithoutError(offer);
3023
deadbeefcbecd352015-09-23 11:50:27 -07003024 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3025 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003026
deadbeefab9b2d12015-10-14 11:33:11 -07003027 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003028
3029 // Remove BUNDLE from the answer.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003030 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003031 CreateRemoteAnswer(session_->local_description()));
3032 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3033 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3034 JsepSessionDescription* modified_answer =
3035 new JsepSessionDescription(JsepSessionDescription::kAnswer);
3036 modified_answer->Initialize(answer_copy, "1", "1");
3037 SetRemoteDescriptionWithoutError(modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003038
deadbeefcbecd352015-09-23 11:50:27 -07003039 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3040 session_->video_rtp_transport_channel());
3041}
3042
3043// kBundlePolicyMaxBundle policy with BUNDLE in the remote offer.
3044TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) {
3045 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003046 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07003047
3048 SessionDescriptionInterface* offer = CreateRemoteOffer();
3049 SetRemoteDescriptionWithoutError(offer);
3050
3051 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3052 session_->video_rtp_transport_channel());
3053
deadbeefab9b2d12015-10-14 11:33:11 -07003054 SendAudioVideoStream2();
deadbeefcbecd352015-09-23 11:50:27 -07003055 SessionDescriptionInterface* answer = CreateAnswer(nullptr);
3056 SetLocalDescriptionWithoutError(answer);
3057
3058 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3059 session_->video_rtp_transport_channel());
3060}
3061
3062// kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer.
3063TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) {
3064 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003065 SendAudioVideoStream1();
deadbeefcbecd352015-09-23 11:50:27 -07003066
3067 // Remove BUNDLE from the offer.
3068 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
3069 cricket::SessionDescription* offer_copy = offer->description()->Copy();
3070 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3071 JsepSessionDescription* modified_offer =
3072 new JsepSessionDescription(JsepSessionDescription::kOffer);
3073 modified_offer->Initialize(offer_copy, "1", "1");
3074
3075 // Expect an error when applying the remote description
3076 SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer,
3077 kCreateChannelFailed, modified_offer);
Donald Curtis0e209b02015-03-24 09:29:54 -07003078}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003079
Peter Thatcher4eddf182015-04-30 10:55:59 -07003080// kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE.
Donald Curtis0e209b02015-03-24 09:29:54 -07003081TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) {
3082 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07003083 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003084
Donald Curtis0e209b02015-03-24 09:29:54 -07003085 PeerConnectionInterface::RTCOfferAnswerOptions options;
3086 options.use_rtp_mux = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003087
Donald Curtis0e209b02015-03-24 09:29:54 -07003088 SessionDescriptionInterface* offer = CreateOffer(options);
3089 SetLocalDescriptionWithoutError(offer);
3090
deadbeefcbecd352015-09-23 11:50:27 -07003091 EXPECT_NE(session_->voice_rtp_transport_channel(),
3092 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003093
deadbeefab9b2d12015-10-14 11:33:11 -07003094 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003095 SessionDescriptionInterface* answer =
3096 CreateRemoteAnswer(session_->local_description());
3097 SetRemoteDescriptionWithoutError(answer);
3098
3099 // This should lead to an audio-only call but isn't implemented
3100 // correctly yet.
deadbeefcbecd352015-09-23 11:50:27 -07003101 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3102 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003103}
3104
deadbeefcbecd352015-09-23 11:50:27 -07003105// kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer.
Donald Curtis0e209b02015-03-24 09:29:54 -07003106TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) {
3107 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
deadbeefab9b2d12015-10-14 11:33:11 -07003108 SendAudioVideoStream1();
Donald Curtis0e209b02015-03-24 09:29:54 -07003109 PeerConnectionInterface::RTCOfferAnswerOptions options;
3110 options.use_rtp_mux = true;
3111
3112 SessionDescriptionInterface* offer = CreateOffer(options);
3113 SetLocalDescriptionWithoutError(offer);
3114
deadbeefcbecd352015-09-23 11:50:27 -07003115 EXPECT_NE(session_->voice_rtp_transport_channel(),
3116 session_->video_rtp_transport_channel());
Donald Curtis0e209b02015-03-24 09:29:54 -07003117
deadbeefab9b2d12015-10-14 11:33:11 -07003118 SendAudioVideoStream2();
Donald Curtis0e209b02015-03-24 09:29:54 -07003119
3120 // Remove BUNDLE from the answer.
3121 rtc::scoped_ptr<SessionDescriptionInterface> answer(
3122 CreateRemoteAnswer(session_->local_description()));
3123 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3124 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
3125 JsepSessionDescription* modified_answer =
3126 new JsepSessionDescription(JsepSessionDescription::kAnswer);
3127 modified_answer->Initialize(answer_copy, "1", "1");
3128 SetRemoteDescriptionWithoutError(modified_answer); //
3129
deadbeefcbecd352015-09-23 11:50:27 -07003130 EXPECT_NE(session_->voice_rtp_transport_channel(),
3131 session_->video_rtp_transport_channel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003132}
3133
Peter Thatcher4eddf182015-04-30 10:55:59 -07003134// kBundlePolicyMaxbundle and then we call SetRemoteDescription first.
3135TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) {
3136 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle);
deadbeefab9b2d12015-10-14 11:33:11 -07003137 SendAudioVideoStream1();
Peter Thatcher4eddf182015-04-30 10:55:59 -07003138
3139 PeerConnectionInterface::RTCOfferAnswerOptions options;
3140 options.use_rtp_mux = true;
3141
3142 SessionDescriptionInterface* offer = CreateOffer(options);
3143 SetRemoteDescriptionWithoutError(offer);
3144
deadbeefcbecd352015-09-23 11:50:27 -07003145 EXPECT_EQ(session_->voice_rtp_transport_channel(),
3146 session_->video_rtp_transport_channel());
Peter Thatcher4eddf182015-04-30 10:55:59 -07003147}
3148
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003149TEST_F(WebRtcSessionTest, TestRequireRtcpMux) {
3150 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire);
deadbeefab9b2d12015-10-14 11:33:11 -07003151 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003152
3153 PeerConnectionInterface::RTCOfferAnswerOptions options;
3154 SessionDescriptionInterface* offer = CreateOffer(options);
3155 SetLocalDescriptionWithoutError(offer);
3156
deadbeefcbecd352015-09-23 11:50:27 -07003157 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3158 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003159
deadbeefab9b2d12015-10-14 11:33:11 -07003160 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003161 SessionDescriptionInterface* answer =
3162 CreateRemoteAnswer(session_->local_description());
3163 SetRemoteDescriptionWithoutError(answer);
3164
deadbeefcbecd352015-09-23 11:50:27 -07003165 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3166 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003167}
3168
3169TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) {
3170 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyNegotiate);
deadbeefab9b2d12015-10-14 11:33:11 -07003171 SendAudioVideoStream1();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003172
3173 PeerConnectionInterface::RTCOfferAnswerOptions options;
3174 SessionDescriptionInterface* offer = CreateOffer(options);
3175 SetLocalDescriptionWithoutError(offer);
3176
deadbeefcbecd352015-09-23 11:50:27 -07003177 EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL);
3178 EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003179
deadbeefab9b2d12015-10-14 11:33:11 -07003180 SendAudioVideoStream2();
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003181 SessionDescriptionInterface* answer =
3182 CreateRemoteAnswer(session_->local_description());
3183 SetRemoteDescriptionWithoutError(answer);
3184
deadbeefcbecd352015-09-23 11:50:27 -07003185 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL);
3186 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL);
Peter Thatcheraf55ccc2015-05-21 07:48:41 -07003187}
3188
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003189// This test verifies that SetLocalDescription and SetRemoteDescription fails
3190// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
3191TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003192 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003193 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003194
3195 PeerConnectionInterface::RTCOfferAnswerOptions options;
3196 options.use_rtp_mux = true;
3197
3198 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003199 std::string offer_str;
3200 offer->ToString(&offer_str);
3201 // Disable rtcp-mux
3202 const std::string rtcp_mux = "rtcp-mux";
3203 const std::string xrtcp_mux = "xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003204 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003205 xrtcp_mux.c_str(), xrtcp_mux.length(),
3206 &offer_str);
deadbeefcbecd352015-09-23 11:50:27 -07003207 JsepSessionDescription* local_offer =
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003208 new JsepSessionDescription(JsepSessionDescription::kOffer);
3209 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003210 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
deadbeefcbecd352015-09-23 11:50:27 -07003211 JsepSessionDescription* remote_offer =
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003212 new JsepSessionDescription(JsepSessionDescription::kOffer);
3213 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003214 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003215 // Trying unmodified SDP.
3216 SetLocalDescriptionWithoutError(offer);
3217}
3218
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003219TEST_F(WebRtcSessionTest, SetAudioPlayout) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003220 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003221 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003222 CreateAndSetRemoteOfferAndLocalAnswer();
3223 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3224 ASSERT_TRUE(channel != NULL);
3225 ASSERT_EQ(1u, channel->recv_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003226 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
solenberg4bac9c52015-10-09 02:32:53 -07003227 double volume;
3228 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3229 EXPECT_EQ(1, volume);
solenbergd4cec0d2015-10-09 08:55:48 -07003230 session_->SetAudioPlayout(receive_ssrc, false);
solenberg4bac9c52015-10-09 02:32:53 -07003231 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3232 EXPECT_EQ(0, volume);
solenbergd4cec0d2015-10-09 08:55:48 -07003233 session_->SetAudioPlayout(receive_ssrc, true);
solenberg4bac9c52015-10-09 02:32:53 -07003234 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume));
3235 EXPECT_EQ(1, volume);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003236}
3237
3238TEST_F(WebRtcSessionTest, SetAudioSend) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003239 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003240 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003241 CreateAndSetRemoteOfferAndLocalAnswer();
3242 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3243 ASSERT_TRUE(channel != NULL);
3244 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003245 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003246 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3247
3248 cricket::AudioOptions options;
3249 options.echo_cancellation.Set(true);
3250
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003251 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003252 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003253 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
3254 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003255 EXPECT_TRUE(renderer->sink() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003256
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003257 // This will trigger SetSink(NULL) to the |renderer|.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00003258 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003259 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3260 bool value;
3261 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
3262 EXPECT_TRUE(value);
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003263 EXPECT_TRUE(renderer->sink() == NULL);
3264}
3265
3266TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003267 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003268 SendAudioVideoStream1();
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003269 CreateAndSetRemoteOfferAndLocalAnswer();
3270 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3271 ASSERT_TRUE(channel != NULL);
3272 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003273 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003274
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003275 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00003276 cricket::AudioOptions options;
3277 session_->SetAudioSend(send_ssrc, true, options, renderer.get());
3278 EXPECT_TRUE(renderer->sink() != NULL);
3279
3280 // Delete the |renderer| and it will trigger OnClose() to the sink, and this
3281 // will invalidate the |renderer_| pointer in the sink and prevent getting a
3282 // SetSink(NULL) callback afterwards.
3283 renderer.reset();
3284
3285 // This will trigger SetSink(NULL) if no OnClose() callback.
3286 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003287}
3288
3289TEST_F(WebRtcSessionTest, SetVideoPlayout) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003290 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003291 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003292 CreateAndSetRemoteOfferAndLocalAnswer();
3293 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
3294 ASSERT_TRUE(channel != NULL);
3295 ASSERT_LT(0u, channel->renderers().size());
3296 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
3297 ASSERT_EQ(1u, channel->recv_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003298 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003299 cricket::FakeVideoRenderer renderer;
3300 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
3301 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
3302 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
3303 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
3304}
3305
3306TEST_F(WebRtcSessionTest, SetVideoSend) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003307 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003308 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003309 CreateAndSetRemoteOfferAndLocalAnswer();
3310 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
3311 ASSERT_TRUE(channel != NULL);
3312 ASSERT_EQ(1u, channel->send_streams().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003313 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003314 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3315 cricket::VideoOptions* options = NULL;
3316 session_->SetVideoSend(send_ssrc, false, options);
3317 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
3318 session_->SetVideoSend(send_ssrc, true, options);
3319 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
3320}
3321
3322TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
3323 TestCanInsertDtmf(false);
3324}
3325
3326TEST_F(WebRtcSessionTest, CanInsertDtmf) {
3327 TestCanInsertDtmf(true);
3328}
3329
3330TEST_F(WebRtcSessionTest, InsertDtmf) {
3331 // Setup
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003332 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003333 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003334 CreateAndSetRemoteOfferAndLocalAnswer();
3335 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
3336 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
3337
3338 // Insert DTMF
3339 const int expected_flags = DF_SEND;
3340 const int expected_duration = 90;
3341 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
3342 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
3343 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
3344
3345 // Verify
3346 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02003347 const uint32_t send_ssrc = channel->send_streams()[0].first_ssrc();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003348 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
3349 expected_duration, expected_flags));
3350 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
3351 expected_duration, expected_flags));
3352 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
3353 expected_duration, expected_flags));
3354}
3355
deadbeefd59daf82015-10-14 15:02:44 -07003356// This test verifies the |initial_offerer| flag when session initiates the
3357// call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003358TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003359 Init();
deadbeefd59daf82015-10-14 15:02:44 -07003360 EXPECT_FALSE(session_->initial_offerer());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003361 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003362 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
3363 SetLocalDescriptionWithoutError(offer);
deadbeefd59daf82015-10-14 15:02:44 -07003364 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003365 SetRemoteDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07003366 EXPECT_TRUE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003367}
3368
deadbeefd59daf82015-10-14 15:02:44 -07003369// This test verifies the |initial_offerer| flag when session receives the call.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003370TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003371 Init();
deadbeefd59daf82015-10-14 15:02:44 -07003372 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003373 SessionDescriptionInterface* offer = CreateRemoteOffer();
3374 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003375 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003376
deadbeefd59daf82015-10-14 15:02:44 -07003377 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003378 SetLocalDescriptionWithoutError(answer);
deadbeefd59daf82015-10-14 15:02:44 -07003379 EXPECT_FALSE(session_->initial_offerer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003380}
3381
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003382// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
3383TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003384 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003385 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003386 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003387 SetLocalDescriptionWithoutError(offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003388 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003389 CreateRemoteAnswer(session_->local_description()));
3390
3391 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3392 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003393 JsepSessionDescription* modified_answer =
3394 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003395
3396 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
3397 answer->session_id(),
3398 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003399 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003400
wu@webrtc.org4e393072014-04-07 17:04:35 +00003401 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003402 std::string sdp;
3403 EXPECT_TRUE(answer->ToString(&sdp));
3404 const std::string kAudioMid = "a=mid:audio";
3405 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003406 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003407 kAudioMidReplaceStr.c_str(),
3408 kAudioMidReplaceStr.length(),
3409 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003410 SessionDescriptionInterface* modified_answer1 =
3411 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003412 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003413
wu@webrtc.org4e393072014-04-07 17:04:35 +00003414 // Different media types.
3415 EXPECT_TRUE(answer->ToString(&sdp));
3416 const std::string kAudioMline = "m=audio";
3417 const std::string kAudioMlineReplaceStr = "m=video";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003418 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
wu@webrtc.org4e393072014-04-07 17:04:35 +00003419 kAudioMlineReplaceStr.c_str(),
3420 kAudioMlineReplaceStr.length(),
3421 &sdp);
3422 SessionDescriptionInterface* modified_answer2 =
3423 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
3424 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
3425
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003426 SetRemoteDescriptionWithoutError(answer.release());
3427}
3428
3429// Verifying remote offer and local answer have matching m-lines as per
3430// RFC 3264.
3431TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003432 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003433 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003434 SessionDescriptionInterface* offer = CreateRemoteOffer();
3435 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003436 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003437
3438 cricket::SessionDescription* answer_copy = answer->description()->Copy();
3439 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003440 JsepSessionDescription* modified_answer =
3441 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003442
3443 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
3444 answer->session_id(),
3445 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003446 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003447 SetLocalDescriptionWithoutError(answer);
3448}
3449
3450// This test verifies that WebRtcSession does not start candidate allocation
3451// before SetLocalDescription is called.
3452TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003453 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003454 SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003455 SessionDescriptionInterface* offer = CreateRemoteOffer();
3456 cricket::Candidate candidate;
3457 candidate.set_component(1);
3458 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
3459 candidate);
3460 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
3461 cricket::Candidate candidate1;
3462 candidate1.set_component(1);
3463 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
3464 candidate1);
3465 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
3466 SetRemoteDescriptionWithoutError(offer);
deadbeefcbecd352015-09-23 11:50:27 -07003467 ASSERT_TRUE(session_->voice_rtp_transport_channel() != NULL);
3468 ASSERT_TRUE(session_->video_rtp_transport_channel() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003469
3470 // Pump for 1 second and verify that no candidates are generated.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003471 rtc::Thread::Current()->ProcessMessages(1000);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003472 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
3473 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
3474
wu@webrtc.org91053e72013-08-10 07:18:04 +00003475 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003476 SetLocalDescriptionWithoutError(answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003477 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
3478}
3479
3480// This test verifies that crypto parameter is updated in local session
3481// description as per security policy set in MediaSessionDescriptionFactory.
3482TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003483 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003484 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003485 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003486
3487 // Making sure SetLocalDescription correctly sets crypto value in
3488 // SessionDescription object after de-serialization of sdp string. The value
3489 // will be set as per MediaSessionDescriptionFactory.
3490 std::string offer_str;
3491 offer->ToString(&offer_str);
3492 SessionDescriptionInterface* jsep_offer_str =
3493 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3494 SetLocalDescriptionWithoutError(jsep_offer_str);
3495 EXPECT_TRUE(session_->voice_channel()->secure_required());
3496 EXPECT_TRUE(session_->video_channel()->secure_required());
3497}
3498
3499// This test verifies the crypto parameter when security is disabled.
3500TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00003501 options_.disable_encryption = true;
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003502 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003503 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003504 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003505
3506 // Making sure SetLocalDescription correctly sets crypto value in
3507 // SessionDescription object after de-serialization of sdp string. The value
3508 // will be set as per MediaSessionDescriptionFactory.
3509 std::string offer_str;
3510 offer->ToString(&offer_str);
deadbeefcbecd352015-09-23 11:50:27 -07003511 SessionDescriptionInterface* jsep_offer_str =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003512 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3513 SetLocalDescriptionWithoutError(jsep_offer_str);
3514 EXPECT_FALSE(session_->voice_channel()->secure_required());
3515 EXPECT_FALSE(session_->video_channel()->secure_required());
3516}
3517
3518// This test verifies that an answer contains new ufrag and password if an offer
3519// with new ufrag and password is received.
3520TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003521 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003522 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003523 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003524 rtc::scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003525 CreateRemoteOffer(options));
3526 SetRemoteDescriptionWithoutError(offer.release());
3527
deadbeefab9b2d12015-10-14 11:33:11 -07003528 SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003529 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003530 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003531 SetLocalDescriptionWithoutError(answer.release());
3532
3533 // Receive an offer with new ufrag and password.
3534 options.transport_options.ice_restart = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003535 rtc::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003536 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003537 SetRemoteDescriptionWithoutError(updated_offer1.release());
3538
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003539 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003540 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003541
3542 CompareIceUfragAndPassword(updated_answer1->description(),
3543 session_->local_description()->description(),
3544 false);
3545
3546 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003547}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003548
wu@webrtc.org91053e72013-08-10 07:18:04 +00003549// This test verifies that an answer contains old ufrag and password if an offer
3550// with old ufrag and password is received.
3551TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003552 Init();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003553 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003554 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003555 rtc::scoped_ptr<JsepSessionDescription> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003556 CreateRemoteOffer(options));
3557 SetRemoteDescriptionWithoutError(offer.release());
3558
deadbeefab9b2d12015-10-14 11:33:11 -07003559 SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003560 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003561 CreateAnswer(NULL));
3562 SetLocalDescriptionWithoutError(answer.release());
3563
3564 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003565 options.transport_options.ice_restart = false;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003566 rtc::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003567 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003568 SetRemoteDescriptionWithoutError(updated_offer2.release());
3569
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003570 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003571 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003572
3573 CompareIceUfragAndPassword(updated_answer2->description(),
3574 session_->local_description()->description(),
3575 true);
3576
3577 SetLocalDescriptionWithoutError(updated_answer2.release());
3578}
3579
3580TEST_F(WebRtcSessionTest, TestSessionContentError) {
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003581 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003582 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003583 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003584 const std::string session_id_orig = offer->session_id();
3585 const std::string session_version_orig = offer->session_version();
3586 SetLocalDescriptionWithoutError(offer);
3587
3588 video_channel_ = media_engine_->GetVideoChannel(0);
3589 video_channel_->set_fail_set_send_codecs(true);
3590
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003591 SessionDescriptionInterface* answer =
3592 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003593 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
deadbeefd59daf82015-10-14 15:02:44 -07003594
3595 // Test that after a content error, setting any description will
3596 // result in an error.
3597 video_channel_->set_fail_set_send_codecs(false);
3598 answer = CreateRemoteAnswer(session_->local_description());
3599 SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer);
3600 offer = CreateRemoteOffer();
3601 SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003602}
3603
3604// Runs the loopback call test with BUNDLE and STUN disabled.
3605TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
3606 // Lets try with only UDP ports.
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003607 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003608 cricket::PORTALLOCATOR_DISABLE_STUN |
3609 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003610 TestLoopbackCall();
3611}
3612
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003613TEST_F(WebRtcSessionTest, TestIceStatesBasicIPv6) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003614 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003615 cricket::PORTALLOCATOR_DISABLE_STUN |
3616 cricket::PORTALLOCATOR_ENABLE_IPV6 |
3617 cricket::PORTALLOCATOR_DISABLE_RELAY);
3618
3619 // best connection is IPv6 since it has higher network preference.
3620 LoopbackNetworkConfiguration config;
3621 config.test_ipv6_network_ = true;
3622 config.best_connection_after_initial_ice_converged_ =
3623 LoopbackNetworkConfiguration::ExpectedBestConnection(0, 1);
3624
3625 TestLoopbackCall(config);
3626}
3627
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00003628// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003629TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
Peter Thatcher7cbd1882015-09-17 18:54:52 -07003630 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
3631 cricket::PORTALLOCATOR_DISABLE_RELAY);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003632 TestLoopbackCall();
3633}
3634
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003635TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
3636 constraints_.reset(new FakeConstraints());
3637 constraints_->AddOptional(
3638 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003639 Init();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003640
3641 SetLocalDescriptionWithDataChannel();
3642 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3643}
3644
Henrik Boström87713d02015-08-25 09:53:21 +02003645TEST_P(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003646 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003647
3648 constraints_.reset(new FakeConstraints());
3649 constraints_->AddOptional(
3650 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org97077a32013-10-25 21:18:33 +00003651 options_.disable_sctp_data_channels = false;
3652
Henrik Boström87713d02015-08-25 09:53:21 +02003653 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003654
3655 SetLocalDescriptionWithDataChannel();
3656 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3657}
3658
Henrik Boström87713d02015-08-25 09:53:21 +02003659TEST_P(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003660 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org967bfff2013-09-19 05:49:50 +00003661
Henrik Boström87713d02015-08-25 09:53:21 +02003662 InitWithDtls(GetParam());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003663
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003664 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003665 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003666 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
3667}
3668
Henrik Boström87713d02015-08-25 09:53:21 +02003669TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003670 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003671 SetFactoryDtlsSrtp();
Henrik Boström87713d02015-08-25 09:53:21 +02003672 InitWithDtls(GetParam());
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003673
3674 // Create remote offer with SCTP.
3675 cricket::MediaSessionOptions options;
3676 options.data_channel_type = cricket::DCT_SCTP;
3677 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003678 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003679 SetRemoteDescriptionWithoutError(offer);
3680
3681 // Verifies the answer contains SCTP.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003682 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003683 EXPECT_TRUE(answer != NULL);
3684 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
3685 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003686}
3687
Henrik Boström87713d02015-08-25 09:53:21 +02003688TEST_P(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003689 constraints_.reset(new FakeConstraints());
3690 constraints_->AddOptional(
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003691 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
Henrik Boström87713d02015-08-25 09:53:21 +02003692 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003693
3694 SetLocalDescriptionWithDataChannel();
3695 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3696}
3697
Henrik Boström87713d02015-08-25 09:53:21 +02003698TEST_P(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003699 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003700
Henrik Boström87713d02015-08-25 09:53:21 +02003701 InitWithDtls(GetParam());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003702
3703 SetLocalDescriptionWithDataChannel();
3704 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3705}
wu@webrtc.org91053e72013-08-10 07:18:04 +00003706
Henrik Boström87713d02015-08-25 09:53:21 +02003707TEST_P(WebRtcSessionTest, TestDisableSctpDataChannels) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003708 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org97077a32013-10-25 21:18:33 +00003709 options_.disable_sctp_data_channels = true;
Henrik Boström87713d02015-08-25 09:53:21 +02003710 InitWithDtls(GetParam());
wu@webrtc.org97077a32013-10-25 21:18:33 +00003711
3712 SetLocalDescriptionWithDataChannel();
3713 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3714}
3715
Henrik Boström87713d02015-08-25 09:53:21 +02003716TEST_P(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003717 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003718 const int new_send_port = 9998;
3719 const int new_recv_port = 7775;
3720
Henrik Boström87713d02015-08-25 09:53:21 +02003721 InitWithDtls(GetParam());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003722 SetFactoryDtlsSrtp();
3723
3724 // By default, don't actually add the codecs to desc_factory_; they don't
3725 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
3726 // let the session description get parsed. That'll get the proper codecs
3727 // into the stream.
3728 cricket::MediaSessionOptions options;
3729 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
3730 "stream1", new_send_port, options);
3731
3732 // SetRemoteDescription will take the ownership of the offer.
3733 SetRemoteDescriptionWithoutError(offer);
3734
3735 SessionDescriptionInterface* answer = ChangeSDPSctpPort(
3736 new_recv_port, CreateAnswer(NULL));
3737 ASSERT_TRUE(answer != NULL);
3738
3739 // Now set the local description, which'll take ownership of the answer.
3740 SetLocalDescriptionWithoutError(answer);
3741
3742 // TEST PLAN: Set the port number to something new, set it in the SDP,
3743 // and pass it all the way down.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003744 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
deadbeefab9b2d12015-10-14 11:33:11 -07003745 CreateDataChannel();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003746
3747 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
3748 int portnum = -1;
3749 ASSERT_TRUE(ch != NULL);
3750 ASSERT_EQ(1UL, ch->send_codecs().size());
3751 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
Donald Curtisd4f769d2015-05-28 09:48:21 -07003752 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003753 ch->send_codecs()[0].name.c_str()));
3754 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
3755 &portnum));
3756 EXPECT_EQ(new_send_port, portnum);
3757
3758 ASSERT_EQ(1UL, ch->recv_codecs().size());
3759 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
Donald Curtisd4f769d2015-05-28 09:48:21 -07003760 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003761 ch->recv_codecs()[0].name.c_str()));
3762 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
3763 &portnum));
3764 EXPECT_EQ(new_recv_port, portnum);
3765}
3766
deadbeefab9b2d12015-10-14 11:33:11 -07003767// Verifies that when a session's DataChannel receives an OPEN message,
3768// WebRtcSession signals the DataChannel creation request with the expected
3769// config.
3770TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) {
3771 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
3772
3773 InitWithDtls(GetParam());
3774
3775 SetLocalDescriptionWithDataChannel();
3776 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3777
3778 webrtc::DataChannelInit config;
3779 config.id = 1;
3780 rtc::Buffer payload;
3781 webrtc::WriteDataChannelOpenMessage("a", config, &payload);
3782 cricket::ReceiveDataParams params;
3783 params.ssrc = config.id;
3784 params.type = cricket::DMT_CONTROL;
3785
3786 cricket::DataChannel* data_channel = session_->data_channel();
3787 data_channel->SignalDataReceived(data_channel, params, payload);
3788
3789 EXPECT_EQ("a", last_data_channel_label_);
3790 EXPECT_EQ(config.id, last_data_channel_config_.id);
3791 EXPECT_FALSE(last_data_channel_config_.negotiated);
3792 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
3793 last_data_channel_config_.open_handshake_role);
3794}
3795
3796TEST_P(WebRtcSessionTest, TestUsesProvidedCertificate) {
Henrik Boströmd8281982015-08-27 10:12:24 +02003797 rtc::scoped_refptr<rtc::RTCCertificate> certificate =
3798 FakeDtlsIdentityStore::GenerateCertificate();
3799
3800 PeerConnectionInterface::RTCConfiguration configuration;
3801 configuration.certificates.push_back(certificate);
3802 Init(nullptr, configuration);
3803 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
3804
3805 EXPECT_EQ(session_->certificate_for_testing(), certificate);
3806}
wu@webrtc.org91053e72013-08-10 07:18:04 +00003807
Henrik Boström87713d02015-08-25 09:53:21 +02003808// Verifies that CreateOffer succeeds when CreateOffer is called before async
3809// identity generation is finished (even if a certificate is provided this is
3810// an async op).
3811TEST_P(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
3812 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
3813 InitWithDtls(GetParam());
3814
Henrik Boströmd8281982015-08-27 10:12:24 +02003815 EXPECT_TRUE(session_->waiting_for_certificate_for_testing());
deadbeefab9b2d12015-10-14 11:33:11 -07003816 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003817 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
3818
wu@webrtc.org91053e72013-08-10 07:18:04 +00003819 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003820 VerifyNoCryptoParams(offer->description(), true);
3821 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003822}
3823
3824// Verifies that CreateAnswer succeeds when CreateOffer is called before async
Henrik Boström87713d02015-08-25 09:53:21 +02003825// identity generation is finished (even if a certificate is provided this is
3826// an async op).
3827TEST_P(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003828 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02003829 InitWithDtls(GetParam());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003830 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003831
3832 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003833 options.recv_video = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003834 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003835 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003836 ASSERT_TRUE(offer.get() != NULL);
3837 SetRemoteDescriptionWithoutError(offer.release());
3838
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003839 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003840 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003841 VerifyNoCryptoParams(answer->description(), true);
3842 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003843}
3844
3845// Verifies that CreateOffer succeeds when CreateOffer is called after async
Henrik Boström87713d02015-08-25 09:53:21 +02003846// identity generation is finished (even if a certificate is provided this is
3847// an async op).
3848TEST_P(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003849 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02003850 InitWithDtls(GetParam());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003851
Henrik Boströmd8281982015-08-27 10:12:24 +02003852 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003853
3854 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003855 EXPECT_TRUE(offer != NULL);
3856}
3857
3858// Verifies that CreateOffer fails when CreateOffer is called after async
3859// identity generation fails.
3860TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003861 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02003862 InitWithDtlsIdentityGenFail();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003863
Henrik Boströmd8281982015-08-27 10:12:24 +02003864 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003865
3866 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003867 EXPECT_TRUE(offer == NULL);
3868}
3869
3870// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
3871// before async identity generation is finished.
Henrik Boström87713d02015-08-25 09:53:21 +02003872TEST_P(WebRtcSessionTest,
wu@webrtc.org91053e72013-08-10 07:18:04 +00003873 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003874 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
deadbeefcbecd352015-09-23 11:50:27 -07003875 VerifyMultipleAsyncCreateDescription(GetParam(),
3876 CreateSessionDescriptionRequest::kOffer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003877}
3878
3879// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
3880// before async identity generation fails.
3881TEST_F(WebRtcSessionTest,
3882 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003883 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02003884 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
3885 CreateSessionDescriptionRequest::kOffer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003886}
3887
3888// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
3889// before async identity generation is finished.
Henrik Boström87713d02015-08-25 09:53:21 +02003890TEST_P(WebRtcSessionTest,
wu@webrtc.org91053e72013-08-10 07:18:04 +00003891 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003892 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003893 VerifyMultipleAsyncCreateDescription(
Henrik Boström87713d02015-08-25 09:53:21 +02003894 GetParam(), CreateSessionDescriptionRequest::kAnswer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003895}
3896
3897// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
3898// before async identity generation fails.
3899TEST_F(WebRtcSessionTest,
3900 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003901 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02003902 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure(
3903 CreateSessionDescriptionRequest::kAnswer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003904}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003905
3906// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
3907// offer has no SDES crypto but only DTLS fingerprint.
3908TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
3909 // Init without DTLS.
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003910 Init();
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003911 // Create a remote offer with secured transport disabled.
3912 cricket::MediaSessionOptions options;
3913 JsepSessionDescription* offer(CreateRemoteOffer(
3914 options, cricket::SEC_DISABLED));
3915 // Adds a DTLS fingerprint to the remote offer.
3916 cricket::SessionDescription* sdp = offer->description();
3917 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
3918 ASSERT_TRUE(audio != NULL);
3919 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
3920 audio->description.identity_fingerprint.reset(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003921 rtc::SSLFingerprint::CreateFromRfc4572(
3922 rtc::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003923 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003924 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003925}
3926
wu@webrtc.orgde305012013-10-31 15:40:38 +00003927// This test verifies DSCP is properly applied on the media channels.
3928TEST_F(WebRtcSessionTest, TestDscpConstraint) {
3929 constraints_.reset(new FakeConstraints());
3930 constraints_->AddOptional(
3931 webrtc::MediaConstraintsInterface::kEnableDscp, true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003932 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003933 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003934 SessionDescriptionInterface* offer = CreateOffer();
wu@webrtc.orgde305012013-10-31 15:40:38 +00003935
3936 SetLocalDescriptionWithoutError(offer);
3937
3938 video_channel_ = media_engine_->GetVideoChannel(0);
3939 voice_channel_ = media_engine_->GetVoiceChannel(0);
3940
3941 ASSERT_TRUE(video_channel_ != NULL);
3942 ASSERT_TRUE(voice_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -07003943 const cricket::AudioOptions& audio_options = voice_channel_->options();
3944 const cricket::VideoOptions& video_options = video_channel_->options();
wu@webrtc.orgde305012013-10-31 15:40:38 +00003945 EXPECT_TRUE(audio_options.dscp.IsSet());
3946 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
3947 EXPECT_TRUE(video_options.dscp.IsSet());
3948 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
3949}
3950
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003951TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) {
3952 constraints_.reset(new FakeConstraints());
3953 constraints_->AddOptional(
3954 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
3955 true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003956 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003957 SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003958 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003959
3960 SetLocalDescriptionWithoutError(offer);
3961
3962 video_channel_ = media_engine_->GetVideoChannel(0);
3963
3964 ASSERT_TRUE(video_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -07003965 const cricket::VideoOptions& video_options = video_channel_->options();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003966 EXPECT_TRUE(
3967 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false));
3968}
3969
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +00003970TEST_F(WebRtcSessionTest, TestNumUnsignalledRecvStreamsConstraint) {
3971 // Number of unsignalled receiving streams should be between 0 and
3972 // kMaxUnsignalledRecvStreams.
3973 SetAndVerifyNumUnsignalledRecvStreams(10, 10);
3974 SetAndVerifyNumUnsignalledRecvStreams(kMaxUnsignalledRecvStreams + 1,
3975 kMaxUnsignalledRecvStreams);
3976 SetAndVerifyNumUnsignalledRecvStreams(-1, 0);
3977}
3978
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00003979TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) {
3980 constraints_.reset(new FakeConstraints());
3981 constraints_->AddOptional(
3982 webrtc::MediaConstraintsInterface::kCombinedAudioVideoBwe,
3983 true);
pthatcher@webrtc.org877ac762015-02-04 22:03:09 +00003984 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07003985 SendAudioVideoStream1();
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00003986 SessionDescriptionInterface* offer = CreateOffer();
3987
3988 SetLocalDescriptionWithoutError(offer);
3989
3990 voice_channel_ = media_engine_->GetVoiceChannel(0);
3991
3992 ASSERT_TRUE(voice_channel_ != NULL);
solenberg66f43392015-09-09 01:36:22 -07003993 const cricket::AudioOptions& audio_options = voice_channel_->options();
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00003994 EXPECT_TRUE(
3995 audio_options.combined_audio_video_bwe.GetWithDefaultIfUnset(false));
3996}
3997
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003998// Tests that we can renegotiate new media content with ICE candidates in the
3999// new remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02004000TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004001 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004002 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004003 SetFactoryDtlsSrtp();
4004
deadbeefab9b2d12015-10-14 11:33:11 -07004005 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004006 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004007 SetLocalDescriptionWithoutError(offer);
4008
4009 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
4010 SetRemoteDescriptionWithoutError(answer);
4011
4012 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00004013 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004014 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
4015
4016 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004017 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004018 candidate1.set_component(1);
4019 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
4020 candidate1);
4021 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
4022 SetRemoteDescriptionWithoutError(offer);
4023
4024 answer = CreateAnswer(NULL);
4025 SetLocalDescriptionWithoutError(answer);
4026}
4027
4028// Tests that we can renegotiate new media content with ICE candidates separated
4029// from the remote SDP.
Henrik Boström87713d02015-08-25 09:53:21 +02004030TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004031 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
Henrik Boström87713d02015-08-25 09:53:21 +02004032 InitWithDtls(GetParam());
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004033 SetFactoryDtlsSrtp();
4034
deadbeefab9b2d12015-10-14 11:33:11 -07004035 SendAudioOnlyStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00004036 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004037 SetLocalDescriptionWithoutError(offer);
4038
4039 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
4040 SetRemoteDescriptionWithoutError(answer);
4041
4042 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00004043 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004044 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
4045 SetRemoteDescriptionWithoutError(offer);
4046
4047 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00004048 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004049 candidate1.set_component(1);
4050 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
4051 candidate1);
4052 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate));
4053
4054 answer = CreateAnswer(NULL);
4055 SetLocalDescriptionWithoutError(answer);
4056}
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004057// Tests that RTX codec is removed from the answer when it isn't supported
4058// by local side.
4059TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
4060 Init();
deadbeefab9b2d12015-10-14 11:33:11 -07004061 SendAudioVideoStream1();
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00004062 std::string offer_sdp(kSdpWithRtx);
4063
4064 SessionDescriptionInterface* offer =
4065 CreateSessionDescription(JsepSessionDescription::kOffer, offer_sdp, NULL);
4066 EXPECT_TRUE(offer->ToString(&offer_sdp));
4067
4068 // Offer SDP contains the RTX codec.
4069 EXPECT_TRUE(offer_sdp.find("rtx") != std::string::npos);
4070 SetRemoteDescriptionWithoutError(offer);
4071
4072 SessionDescriptionInterface* answer = CreateAnswer(NULL);
4073 std::string answer_sdp;
4074 answer->ToString(&answer_sdp);
4075 // Answer SDP removes the unsupported RTX codec.
4076 EXPECT_TRUE(answer_sdp.find("rtx") == std::string::npos);
4077 SetLocalDescriptionWithoutError(answer);
4078}
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00004079
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004080// This verifies that the voice channel after bundle has both options from video
4081// and voice channels.
4082TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) {
4083 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
deadbeefab9b2d12015-10-14 11:33:11 -07004084 SendAudioVideoStream1();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004085
4086 PeerConnectionInterface::RTCOfferAnswerOptions options;
4087 options.use_rtp_mux = true;
4088
4089 SessionDescriptionInterface* offer = CreateOffer(options);
4090 SetLocalDescriptionWithoutError(offer);
4091
4092 session_->video_channel()->SetOption(cricket::BaseChannel::ST_RTP,
4093 rtc::Socket::Option::OPT_SNDBUF, 4000);
4094
4095 session_->voice_channel()->SetOption(cricket::BaseChannel::ST_RTP,
4096 rtc::Socket::Option::OPT_RCVBUF, 8000);
4097
4098 int option_val;
deadbeefcbecd352015-09-23 11:50:27 -07004099 EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004100 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4101 EXPECT_EQ(4000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07004102 EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004103 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4104
deadbeefcbecd352015-09-23 11:50:27 -07004105 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004106 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4107 EXPECT_EQ(8000, option_val);
deadbeefcbecd352015-09-23 11:50:27 -07004108 EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004109 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4110
deadbeefcbecd352015-09-23 11:50:27 -07004111 EXPECT_NE(session_->voice_rtp_transport_channel(),
4112 session_->video_rtp_transport_channel());
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004113
deadbeefab9b2d12015-10-14 11:33:11 -07004114 SendAudioVideoStream2();
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004115 SessionDescriptionInterface* answer =
4116 CreateRemoteAnswer(session_->local_description());
4117 SetRemoteDescriptionWithoutError(answer);
4118
deadbeefcbecd352015-09-23 11:50:27 -07004119 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004120 rtc::Socket::Option::OPT_SNDBUF, &option_val));
4121 EXPECT_EQ(4000, option_val);
4122
deadbeefcbecd352015-09-23 11:50:27 -07004123 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption(
guoweis@webrtc.org4f852882015-03-12 20:09:44 +00004124 rtc::Socket::Option::OPT_RCVBUF, &option_val));
4125 EXPECT_EQ(8000, option_val);
4126}
4127
tommi0f620f42015-07-09 03:25:02 -07004128// Test creating a session, request multiple offers, destroy the session
4129// and make sure we got success/failure callbacks for all of the requests.
4130// Background: crbug.com/507307
4131TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) {
4132 Init();
4133
4134 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observers[100];
4135 PeerConnectionInterface::RTCOfferAnswerOptions options;
4136 options.offer_to_receive_audio =
4137 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
deadbeefab9b2d12015-10-14 11:33:11 -07004138 cricket::MediaSessionOptions session_options;
4139 session_options.recv_audio = true;
tommi0f620f42015-07-09 03:25:02 -07004140
4141 for (auto& o : observers) {
4142 o = new WebRtcSessionCreateSDPObserverForTest();
deadbeefab9b2d12015-10-14 11:33:11 -07004143 session_->CreateOffer(o, options, session_options);
tommi0f620f42015-07-09 03:25:02 -07004144 }
4145
4146 session_.reset();
4147
tommi0f620f42015-07-09 03:25:02 -07004148 for (auto& o : observers) {
4149 // We expect to have received a notification now even if the session was
4150 // terminated. The offer creation may or may not have succeeded, but we
4151 // must have received a notification which, so the only invalid state
4152 // is kInit.
4153 EXPECT_NE(WebRtcSessionCreateSDPObserverForTest::kInit, o->state());
4154 }
4155}
4156
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004157// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
4158// currently fails because upon disconnection and reconnection OnIceComplete is
4159// called more than once without returning to IceGatheringGathering.
Henrik Boström87713d02015-08-25 09:53:21 +02004160
deadbeefcbecd352015-09-23 11:50:27 -07004161INSTANTIATE_TEST_CASE_P(WebRtcSessionTests,
4162 WebRtcSessionTest,
4163 testing::Values(ALREADY_GENERATED,
4164 DTLS_IDENTITY_STORE));