blob: 098f8aee692fc5c8112e718b9e436827747ae077 [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
28#include <string>
kwiberg0eb15ed2015-12-17 03:04:15 -080029#include <utility>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
deadbeefab9b2d12015-10-14 11:33:11 -070031#include "talk/app/webrtc/audiotrack.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032#include "talk/app/webrtc/fakeportallocatorfactory.h"
33#include "talk/app/webrtc/jsepsessiondescription.h"
deadbeefab9b2d12015-10-14 11:33:11 -070034#include "talk/app/webrtc/mediastream.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035#include "talk/app/webrtc/mediastreaminterface.h"
deadbeefab9b2d12015-10-14 11:33:11 -070036#include "talk/app/webrtc/peerconnection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/app/webrtc/peerconnectioninterface.h"
deadbeefab9b2d12015-10-14 11:33:11 -070038#include "talk/app/webrtc/rtpreceiverinterface.h"
39#include "talk/app/webrtc/rtpsenderinterface.h"
40#include "talk/app/webrtc/streamcollection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041#include "talk/app/webrtc/test/fakeconstraints.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020042#include "talk/app/webrtc/test/fakedtlsidentitystore.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
44#include "talk/app/webrtc/test/testsdpstrings.h"
wu@webrtc.org967bfff2013-09-19 05:49:50 +000045#include "talk/app/webrtc/videosource.h"
deadbeefab9b2d12015-10-14 11:33:11 -070046#include "talk/app/webrtc/videotrack.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000047#include "talk/media/base/fakevideocapturer.h"
48#include "talk/media/sctp/sctpdataengine.h"
49#include "talk/session/media/mediasession.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000050#include "webrtc/base/gunit.h"
51#include "webrtc/base/scoped_ptr.h"
52#include "webrtc/base/ssladapter.h"
53#include "webrtc/base/sslstreamadapter.h"
54#include "webrtc/base/stringutils.h"
55#include "webrtc/base/thread.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056
57static const char kStreamLabel1[] = "local_stream_1";
58static const char kStreamLabel2[] = "local_stream_2";
59static const char kStreamLabel3[] = "local_stream_3";
60static const int kDefaultStunPort = 3478;
61static const char kStunAddressOnly[] = "stun:address";
62static const char kStunInvalidPort[] = "stun:address:-1";
63static const char kStunAddressPortAndMore1[] = "stun:address:port:more";
64static const char kStunAddressPortAndMore2[] = "stun:address:port more";
65static const char kTurnIceServerUri[] = "turn:user@turn.example.org";
66static const char kTurnUsername[] = "user";
67static const char kTurnPassword[] = "password";
68static const char kTurnHostname[] = "turn.example.org";
Peter Boström0c4e06b2015-10-07 12:23:21 +020069static const uint32_t kTimeout = 10000U;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000070
deadbeefab9b2d12015-10-14 11:33:11 -070071static const char kStreams[][8] = {"stream1", "stream2"};
72static const char kAudioTracks[][32] = {"audiotrack0", "audiotrack1"};
73static const char kVideoTracks[][32] = {"videotrack0", "videotrack1"};
74
deadbeef5e97fb52015-10-15 12:49:08 -070075static const char kRecvonly[] = "recvonly";
76static const char kSendrecv[] = "sendrecv";
77
deadbeefab9b2d12015-10-14 11:33:11 -070078// Reference SDP with a MediaStream with label "stream1" and audio track with
79// id "audio_1" and a video track with id "video_1;
80static const char kSdpStringWithStream1[] =
81 "v=0\r\n"
82 "o=- 0 0 IN IP4 127.0.0.1\r\n"
83 "s=-\r\n"
84 "t=0 0\r\n"
85 "a=ice-ufrag:e5785931\r\n"
86 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
87 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
88 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
89 "m=audio 1 RTP/AVPF 103\r\n"
90 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -070091 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -070092 "a=rtpmap:103 ISAC/16000\r\n"
93 "a=ssrc:1 cname:stream1\r\n"
94 "a=ssrc:1 mslabel:stream1\r\n"
95 "a=ssrc:1 label:audiotrack0\r\n"
96 "m=video 1 RTP/AVPF 120\r\n"
97 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -070098 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -070099 "a=rtpmap:120 VP8/90000\r\n"
100 "a=ssrc:2 cname:stream1\r\n"
101 "a=ssrc:2 mslabel:stream1\r\n"
102 "a=ssrc:2 label:videotrack0\r\n";
103
104// Reference SDP with two MediaStreams with label "stream1" and "stream2. Each
105// MediaStreams have one audio track and one video track.
106// This uses MSID.
107static const char kSdpStringWithStream1And2[] =
108 "v=0\r\n"
109 "o=- 0 0 IN IP4 127.0.0.1\r\n"
110 "s=-\r\n"
111 "t=0 0\r\n"
112 "a=ice-ufrag:e5785931\r\n"
113 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
114 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
115 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
116 "a=msid-semantic: WMS stream1 stream2\r\n"
117 "m=audio 1 RTP/AVPF 103\r\n"
118 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700119 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700120 "a=rtpmap:103 ISAC/16000\r\n"
121 "a=ssrc:1 cname:stream1\r\n"
122 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
123 "a=ssrc:3 cname:stream2\r\n"
124 "a=ssrc:3 msid:stream2 audiotrack1\r\n"
125 "m=video 1 RTP/AVPF 120\r\n"
126 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700127 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700128 "a=rtpmap:120 VP8/0\r\n"
129 "a=ssrc:2 cname:stream1\r\n"
130 "a=ssrc:2 msid:stream1 videotrack0\r\n"
131 "a=ssrc:4 cname:stream2\r\n"
132 "a=ssrc:4 msid:stream2 videotrack1\r\n";
133
134// Reference SDP without MediaStreams. Msid is not supported.
135static const char kSdpStringWithoutStreams[] =
136 "v=0\r\n"
137 "o=- 0 0 IN IP4 127.0.0.1\r\n"
138 "s=-\r\n"
139 "t=0 0\r\n"
140 "a=ice-ufrag:e5785931\r\n"
141 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
142 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
143 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
144 "m=audio 1 RTP/AVPF 103\r\n"
145 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700146 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700147 "a=rtpmap:103 ISAC/16000\r\n"
148 "m=video 1 RTP/AVPF 120\r\n"
149 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700150 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700151 "a=rtpmap:120 VP8/90000\r\n";
152
153// Reference SDP without MediaStreams. Msid is supported.
154static const char kSdpStringWithMsidWithoutStreams[] =
155 "v=0\r\n"
156 "o=- 0 0 IN IP4 127.0.0.1\r\n"
157 "s=-\r\n"
158 "t=0 0\r\n"
159 "a=ice-ufrag:e5785931\r\n"
160 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
161 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
162 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
163 "a=msid-semantic: WMS\r\n"
164 "m=audio 1 RTP/AVPF 103\r\n"
165 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700166 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700167 "a=rtpmap:103 ISAC/16000\r\n"
168 "m=video 1 RTP/AVPF 120\r\n"
169 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700170 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700171 "a=rtpmap:120 VP8/90000\r\n";
172
173// Reference SDP without MediaStreams and audio only.
174static const char kSdpStringWithoutStreamsAudioOnly[] =
175 "v=0\r\n"
176 "o=- 0 0 IN IP4 127.0.0.1\r\n"
177 "s=-\r\n"
178 "t=0 0\r\n"
179 "a=ice-ufrag:e5785931\r\n"
180 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
181 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
182 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
183 "m=audio 1 RTP/AVPF 103\r\n"
184 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700185 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700186 "a=rtpmap:103 ISAC/16000\r\n";
187
188// Reference SENDONLY SDP without MediaStreams. Msid is not supported.
189static const char kSdpStringSendOnlyWithoutStreams[] =
190 "v=0\r\n"
191 "o=- 0 0 IN IP4 127.0.0.1\r\n"
192 "s=-\r\n"
193 "t=0 0\r\n"
194 "a=ice-ufrag:e5785931\r\n"
195 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
196 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
197 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
198 "m=audio 1 RTP/AVPF 103\r\n"
199 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700200 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700201 "a=sendonly\r\n"
202 "a=rtpmap:103 ISAC/16000\r\n"
203 "m=video 1 RTP/AVPF 120\r\n"
204 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700205 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700206 "a=sendonly\r\n"
207 "a=rtpmap:120 VP8/90000\r\n";
208
209static const char kSdpStringInit[] =
210 "v=0\r\n"
211 "o=- 0 0 IN IP4 127.0.0.1\r\n"
212 "s=-\r\n"
213 "t=0 0\r\n"
214 "a=ice-ufrag:e5785931\r\n"
215 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
216 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
217 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
218 "a=msid-semantic: WMS\r\n";
219
220static const char kSdpStringAudio[] =
221 "m=audio 1 RTP/AVPF 103\r\n"
222 "a=mid:audio\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700223 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700224 "a=rtpmap:103 ISAC/16000\r\n";
225
226static const char kSdpStringVideo[] =
227 "m=video 1 RTP/AVPF 120\r\n"
228 "a=mid:video\r\n"
deadbeef5e97fb52015-10-15 12:49:08 -0700229 "a=sendrecv\r\n"
deadbeefab9b2d12015-10-14 11:33:11 -0700230 "a=rtpmap:120 VP8/90000\r\n";
231
232static const char kSdpStringMs1Audio0[] =
233 "a=ssrc:1 cname:stream1\r\n"
234 "a=ssrc:1 msid:stream1 audiotrack0\r\n";
235
236static const char kSdpStringMs1Video0[] =
237 "a=ssrc:2 cname:stream1\r\n"
238 "a=ssrc:2 msid:stream1 videotrack0\r\n";
239
240static const char kSdpStringMs1Audio1[] =
241 "a=ssrc:3 cname:stream1\r\n"
242 "a=ssrc:3 msid:stream1 audiotrack1\r\n";
243
244static const char kSdpStringMs1Video1[] =
245 "a=ssrc:4 cname:stream1\r\n"
246 "a=ssrc:4 msid:stream1 videotrack1\r\n";
247
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248#define MAYBE_SKIP_TEST(feature) \
249 if (!(feature())) { \
250 LOG(LS_INFO) << "Feature disabled... skipping"; \
251 return; \
252 }
253
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000254using rtc::scoped_ptr;
255using rtc::scoped_refptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256using webrtc::AudioSourceInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700257using webrtc::AudioTrack;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258using webrtc::AudioTrackInterface;
259using webrtc::DataBuffer;
260using webrtc::DataChannelInterface;
261using webrtc::FakeConstraints;
262using webrtc::FakePortAllocatorFactory;
263using webrtc::IceCandidateInterface;
deadbeefc80741f2015-10-22 13:14:45 -0700264using webrtc::MediaConstraintsInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700265using webrtc::MediaStream;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266using webrtc::MediaStreamInterface;
267using webrtc::MediaStreamTrackInterface;
268using webrtc::MockCreateSessionDescriptionObserver;
269using webrtc::MockDataChannelObserver;
270using webrtc::MockSetSessionDescriptionObserver;
271using webrtc::MockStatsObserver;
272using webrtc::PeerConnectionInterface;
273using webrtc::PeerConnectionObserver;
274using webrtc::PortAllocatorFactoryInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700275using webrtc::RtpReceiverInterface;
276using webrtc::RtpSenderInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000277using webrtc::SdpParseError;
278using webrtc::SessionDescriptionInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700279using webrtc::StreamCollection;
280using webrtc::StreamCollectionInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281using webrtc::VideoSourceInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700282using webrtc::VideoTrack;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283using webrtc::VideoTrackInterface;
284
deadbeefab9b2d12015-10-14 11:33:11 -0700285typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
286
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287namespace {
288
289// Gets the first ssrc of given content type from the ContentInfo.
290bool GetFirstSsrc(const cricket::ContentInfo* content_info, int* ssrc) {
291 if (!content_info || !ssrc) {
292 return false;
293 }
294 const cricket::MediaContentDescription* media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000295 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 content_info->description);
297 if (!media_desc || media_desc->streams().empty()) {
298 return false;
299 }
300 *ssrc = media_desc->streams().begin()->first_ssrc();
301 return true;
302}
303
304void SetSsrcToZero(std::string* sdp) {
305 const char kSdpSsrcAtribute[] = "a=ssrc:";
306 const char kSdpSsrcAtributeZero[] = "a=ssrc:0";
307 size_t ssrc_pos = 0;
308 while ((ssrc_pos = sdp->find(kSdpSsrcAtribute, ssrc_pos)) !=
309 std::string::npos) {
310 size_t end_ssrc = sdp->find(" ", ssrc_pos);
311 sdp->replace(ssrc_pos, end_ssrc - ssrc_pos, kSdpSsrcAtributeZero);
312 ssrc_pos = end_ssrc;
313 }
314}
315
deadbeefab9b2d12015-10-14 11:33:11 -0700316// Check if |streams| contains the specified track.
317bool ContainsTrack(const std::vector<cricket::StreamParams>& streams,
318 const std::string& stream_label,
319 const std::string& track_id) {
320 for (const cricket::StreamParams& params : streams) {
321 if (params.sync_label == stream_label && params.id == track_id) {
322 return true;
323 }
324 }
325 return false;
326}
327
328// Check if |senders| contains the specified sender, by id.
329bool ContainsSender(
330 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders,
331 const std::string& id) {
332 for (const auto& sender : senders) {
333 if (sender->id() == id) {
334 return true;
335 }
336 }
337 return false;
338}
339
340// Create a collection of streams.
341// CreateStreamCollection(1) creates a collection that
342// correspond to kSdpStringWithStream1.
343// CreateStreamCollection(2) correspond to kSdpStringWithStream1And2.
344rtc::scoped_refptr<StreamCollection> CreateStreamCollection(
345 int number_of_streams) {
346 rtc::scoped_refptr<StreamCollection> local_collection(
347 StreamCollection::Create());
348
349 for (int i = 0; i < number_of_streams; ++i) {
350 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
351 webrtc::MediaStream::Create(kStreams[i]));
352
353 // Add a local audio track.
354 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
355 webrtc::AudioTrack::Create(kAudioTracks[i], nullptr));
356 stream->AddTrack(audio_track);
357
358 // Add a local video track.
359 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
360 webrtc::VideoTrack::Create(kVideoTracks[i], nullptr));
361 stream->AddTrack(video_track);
362
363 local_collection->AddStream(stream);
364 }
365 return local_collection;
366}
367
368// Check equality of StreamCollections.
369bool CompareStreamCollections(StreamCollectionInterface* s1,
370 StreamCollectionInterface* s2) {
371 if (s1 == nullptr || s2 == nullptr || s1->count() != s2->count()) {
372 return false;
373 }
374
375 for (size_t i = 0; i != s1->count(); ++i) {
376 if (s1->at(i)->label() != s2->at(i)->label()) {
377 return false;
378 }
379 webrtc::AudioTrackVector audio_tracks1 = s1->at(i)->GetAudioTracks();
380 webrtc::AudioTrackVector audio_tracks2 = s2->at(i)->GetAudioTracks();
381 webrtc::VideoTrackVector video_tracks1 = s1->at(i)->GetVideoTracks();
382 webrtc::VideoTrackVector video_tracks2 = s2->at(i)->GetVideoTracks();
383
384 if (audio_tracks1.size() != audio_tracks2.size()) {
385 return false;
386 }
387 for (size_t j = 0; j != audio_tracks1.size(); ++j) {
388 if (audio_tracks1[j]->id() != audio_tracks2[j]->id()) {
389 return false;
390 }
391 }
392 if (video_tracks1.size() != video_tracks2.size()) {
393 return false;
394 }
395 for (size_t j = 0; j != video_tracks1.size(); ++j) {
396 if (video_tracks1[j]->id() != video_tracks2[j]->id()) {
397 return false;
398 }
399 }
400 }
401 return true;
402}
403
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404class MockPeerConnectionObserver : public PeerConnectionObserver {
405 public:
deadbeefab9b2d12015-10-14 11:33:11 -0700406 MockPeerConnectionObserver() : remote_streams_(StreamCollection::Create()) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 ~MockPeerConnectionObserver() {
408 }
409 void SetPeerConnectionInterface(PeerConnectionInterface* pc) {
410 pc_ = pc;
411 if (pc) {
412 state_ = pc_->signaling_state();
413 }
414 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 virtual void OnSignalingChange(
416 PeerConnectionInterface::SignalingState new_state) {
417 EXPECT_EQ(pc_->signaling_state(), new_state);
418 state_ = new_state;
419 }
420 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
421 virtual void OnStateChange(StateType state_changed) {
422 if (pc_.get() == NULL)
423 return;
424 switch (state_changed) {
425 case kSignalingState:
426 // OnSignalingChange and OnStateChange(kSignalingState) should always
427 // be called approximately simultaneously. To ease testing, we require
428 // that they always be called in that order. This check verifies
429 // that OnSignalingChange has just been called.
430 EXPECT_EQ(pc_->signaling_state(), state_);
431 break;
432 case kIceState:
433 ADD_FAILURE();
434 break;
435 default:
436 ADD_FAILURE();
437 break;
438 }
439 }
deadbeefab9b2d12015-10-14 11:33:11 -0700440
441 MediaStreamInterface* RemoteStream(const std::string& label) {
442 return remote_streams_->find(label);
443 }
444 StreamCollectionInterface* remote_streams() const { return remote_streams_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445 virtual void OnAddStream(MediaStreamInterface* stream) {
446 last_added_stream_ = stream;
deadbeefab9b2d12015-10-14 11:33:11 -0700447 remote_streams_->AddStream(stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 }
449 virtual void OnRemoveStream(MediaStreamInterface* stream) {
450 last_removed_stream_ = stream;
deadbeefab9b2d12015-10-14 11:33:11 -0700451 remote_streams_->RemoveStream(stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452 }
453 virtual void OnRenegotiationNeeded() {
454 renegotiation_needed_ = true;
455 }
456 virtual void OnDataChannel(DataChannelInterface* data_channel) {
457 last_datachannel_ = data_channel;
458 }
459
460 virtual void OnIceConnectionChange(
461 PeerConnectionInterface::IceConnectionState new_state) {
462 EXPECT_EQ(pc_->ice_connection_state(), new_state);
463 }
464 virtual void OnIceGatheringChange(
465 PeerConnectionInterface::IceGatheringState new_state) {
466 EXPECT_EQ(pc_->ice_gathering_state(), new_state);
467 }
468 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
469 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew,
470 pc_->ice_gathering_state());
471
472 std::string sdp;
473 EXPECT_TRUE(candidate->ToString(&sdp));
474 EXPECT_LT(0u, sdp.size());
475 last_candidate_.reset(webrtc::CreateIceCandidate(candidate->sdp_mid(),
476 candidate->sdp_mline_index(), sdp, NULL));
477 EXPECT_TRUE(last_candidate_.get() != NULL);
478 }
479 // TODO(bemasc): Remove this once callers transition to OnSignalingChange.
480 virtual void OnIceComplete() {
481 ice_complete_ = true;
482 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
483 // be called approximately simultaneously. For ease of testing, this
484 // check additionally requires that they be called in the above order.
485 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
486 pc_->ice_gathering_state());
487 }
488
489 // Returns the label of the last added stream.
490 // Empty string if no stream have been added.
491 std::string GetLastAddedStreamLabel() {
492 if (last_added_stream_.get())
493 return last_added_stream_->label();
494 return "";
495 }
496 std::string GetLastRemovedStreamLabel() {
497 if (last_removed_stream_.get())
498 return last_removed_stream_->label();
499 return "";
500 }
501
502 scoped_refptr<PeerConnectionInterface> pc_;
503 PeerConnectionInterface::SignalingState state_;
504 scoped_ptr<IceCandidateInterface> last_candidate_;
505 scoped_refptr<DataChannelInterface> last_datachannel_;
deadbeefab9b2d12015-10-14 11:33:11 -0700506 rtc::scoped_refptr<StreamCollection> remote_streams_;
507 bool renegotiation_needed_ = false;
508 bool ice_complete_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509
510 private:
511 scoped_refptr<MediaStreamInterface> last_added_stream_;
512 scoped_refptr<MediaStreamInterface> last_removed_stream_;
513};
514
515} // namespace
deadbeefab9b2d12015-10-14 11:33:11 -0700516
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517class PeerConnectionInterfaceTest : public testing::Test {
518 protected:
519 virtual void SetUp() {
520 pc_factory_ = webrtc::CreatePeerConnectionFactory(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000521 rtc::Thread::Current(), rtc::Thread::Current(), NULL, NULL,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 NULL);
523 ASSERT_TRUE(pc_factory_.get() != NULL);
524 }
525
526 void CreatePeerConnection() {
527 CreatePeerConnection("", "", NULL);
528 }
529
530 void CreatePeerConnection(webrtc::MediaConstraintsInterface* constraints) {
531 CreatePeerConnection("", "", constraints);
532 }
533
534 void CreatePeerConnection(const std::string& uri,
535 const std::string& password,
536 webrtc::MediaConstraintsInterface* constraints) {
537 PeerConnectionInterface::IceServer server;
538 PeerConnectionInterface::IceServers servers;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700539 if (!uri.empty()) {
540 server.uri = uri;
541 server.password = password;
542 servers.push_back(server);
543 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544
545 port_allocator_factory_ = FakePortAllocatorFactory::Create();
jiayl@webrtc.orga576faf2014-01-29 17:45:53 +0000546
buildbot@webrtc.org61c1b8e2014-04-09 06:06:38 +0000547 // DTLS does not work in a loopback call, so is disabled for most of the
548 // tests in this file. We only create a FakeIdentityService if the test
549 // explicitly sets the constraint.
jiayl@webrtc.org61e00b02015-03-04 22:17:38 +0000550 FakeConstraints default_constraints;
551 if (!constraints) {
552 constraints = &default_constraints;
553
554 default_constraints.AddMandatory(
555 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
556 }
557
Henrik Boström5e56c592015-08-11 10:33:13 +0200558 scoped_ptr<webrtc::DtlsIdentityStoreInterface> dtls_identity_store;
jiayl@webrtc.orga576faf2014-01-29 17:45:53 +0000559 bool dtls;
560 if (FindConstraint(constraints,
561 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
562 &dtls,
Henrik Boström5e56c592015-08-11 10:33:13 +0200563 nullptr) && dtls) {
564 dtls_identity_store.reset(new FakeDtlsIdentityStore());
jiayl@webrtc.orga576faf2014-01-29 17:45:53 +0000565 }
kwiberg0eb15ed2015-12-17 03:04:15 -0800566 pc_ = pc_factory_->CreatePeerConnection(
567 servers, constraints, port_allocator_factory_.get(),
568 std::move(dtls_identity_store), &observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000569 ASSERT_TRUE(pc_.get() != NULL);
570 observer_.SetPeerConnectionInterface(pc_.get());
571 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
572 }
573
deadbeef0a6c4ca2015-10-06 11:38:28 -0700574 void CreatePeerConnectionExpectFail(const std::string& uri) {
575 PeerConnectionInterface::IceServer server;
576 PeerConnectionInterface::IceServers servers;
577 server.uri = uri;
578 servers.push_back(server);
579
580 scoped_ptr<webrtc::DtlsIdentityStoreInterface> dtls_identity_store;
581 port_allocator_factory_ = FakePortAllocatorFactory::Create();
582 scoped_refptr<PeerConnectionInterface> pc;
583 pc = pc_factory_->CreatePeerConnection(
584 servers, nullptr, port_allocator_factory_.get(),
kwiberg0eb15ed2015-12-17 03:04:15 -0800585 std::move(dtls_identity_store), &observer_);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700586 ASSERT_EQ(nullptr, pc);
587 }
588
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 void CreatePeerConnectionWithDifferentConfigurations() {
590 CreatePeerConnection(kStunAddressOnly, "", NULL);
591 EXPECT_EQ(1u, port_allocator_factory_->stun_configs().size());
592 EXPECT_EQ(0u, port_allocator_factory_->turn_configs().size());
593 EXPECT_EQ("address",
594 port_allocator_factory_->stun_configs()[0].server.hostname());
595 EXPECT_EQ(kDefaultStunPort,
596 port_allocator_factory_->stun_configs()[0].server.port());
597
deadbeef0a6c4ca2015-10-06 11:38:28 -0700598 CreatePeerConnectionExpectFail(kStunInvalidPort);
599 CreatePeerConnectionExpectFail(kStunAddressPortAndMore1);
600 CreatePeerConnectionExpectFail(kStunAddressPortAndMore2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601
602 CreatePeerConnection(kTurnIceServerUri, kTurnPassword, NULL);
buildbot@webrtc.orgf875f152014-04-14 16:06:21 +0000603 EXPECT_EQ(0u, port_allocator_factory_->stun_configs().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604 EXPECT_EQ(1u, port_allocator_factory_->turn_configs().size());
605 EXPECT_EQ(kTurnUsername,
606 port_allocator_factory_->turn_configs()[0].username);
607 EXPECT_EQ(kTurnPassword,
608 port_allocator_factory_->turn_configs()[0].password);
609 EXPECT_EQ(kTurnHostname,
610 port_allocator_factory_->turn_configs()[0].server.hostname());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 }
612
613 void ReleasePeerConnection() {
614 pc_ = NULL;
615 observer_.SetPeerConnectionInterface(NULL);
616 }
617
deadbeefab9b2d12015-10-14 11:33:11 -0700618 void AddVideoStream(const std::string& label) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 // Create a local stream.
620 scoped_refptr<MediaStreamInterface> stream(
621 pc_factory_->CreateLocalMediaStream(label));
622 scoped_refptr<VideoSourceInterface> video_source(
623 pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer(), NULL));
624 scoped_refptr<VideoTrackInterface> video_track(
625 pc_factory_->CreateVideoTrack(label + "v0", video_source));
626 stream->AddTrack(video_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000627 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000628 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
629 observer_.renegotiation_needed_ = false;
630 }
631
632 void AddVoiceStream(const std::string& label) {
633 // Create a local stream.
634 scoped_refptr<MediaStreamInterface> stream(
635 pc_factory_->CreateLocalMediaStream(label));
636 scoped_refptr<AudioTrackInterface> audio_track(
637 pc_factory_->CreateAudioTrack(label + "a0", NULL));
638 stream->AddTrack(audio_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000639 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
641 observer_.renegotiation_needed_ = false;
642 }
643
644 void AddAudioVideoStream(const std::string& stream_label,
645 const std::string& audio_track_label,
646 const std::string& video_track_label) {
647 // Create a local stream.
648 scoped_refptr<MediaStreamInterface> stream(
649 pc_factory_->CreateLocalMediaStream(stream_label));
650 scoped_refptr<AudioTrackInterface> audio_track(
651 pc_factory_->CreateAudioTrack(
652 audio_track_label, static_cast<AudioSourceInterface*>(NULL)));
653 stream->AddTrack(audio_track.get());
654 scoped_refptr<VideoTrackInterface> video_track(
655 pc_factory_->CreateVideoTrack(video_track_label, NULL));
656 stream->AddTrack(video_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000657 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000658 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
659 observer_.renegotiation_needed_ = false;
660 }
661
deadbeefc80741f2015-10-22 13:14:45 -0700662 bool DoCreateOfferAnswer(SessionDescriptionInterface** desc,
663 bool offer,
664 MediaConstraintsInterface* constraints) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000665 rtc::scoped_refptr<MockCreateSessionDescriptionObserver>
666 observer(new rtc::RefCountedObject<
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 MockCreateSessionDescriptionObserver>());
668 if (offer) {
deadbeefc80741f2015-10-22 13:14:45 -0700669 pc_->CreateOffer(observer, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 } else {
deadbeefc80741f2015-10-22 13:14:45 -0700671 pc_->CreateAnswer(observer, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672 }
673 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
674 *desc = observer->release_desc();
675 return observer->result();
676 }
677
deadbeefc80741f2015-10-22 13:14:45 -0700678 bool DoCreateOffer(SessionDescriptionInterface** desc,
679 MediaConstraintsInterface* constraints) {
680 return DoCreateOfferAnswer(desc, true, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 }
682
deadbeefc80741f2015-10-22 13:14:45 -0700683 bool DoCreateAnswer(SessionDescriptionInterface** desc,
684 MediaConstraintsInterface* constraints) {
685 return DoCreateOfferAnswer(desc, false, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 }
687
688 bool DoSetSessionDescription(SessionDescriptionInterface* desc, bool local) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000689 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
690 observer(new rtc::RefCountedObject<
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 MockSetSessionDescriptionObserver>());
692 if (local) {
693 pc_->SetLocalDescription(observer, desc);
694 } else {
695 pc_->SetRemoteDescription(observer, desc);
696 }
697 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
698 return observer->result();
699 }
700
701 bool DoSetLocalDescription(SessionDescriptionInterface* desc) {
702 return DoSetSessionDescription(desc, true);
703 }
704
705 bool DoSetRemoteDescription(SessionDescriptionInterface* desc) {
706 return DoSetSessionDescription(desc, false);
707 }
708
709 // Calls PeerConnection::GetStats and check the return value.
710 // It does not verify the values in the StatReports since a RTCP packet might
711 // be required.
712 bool DoGetStats(MediaStreamTrackInterface* track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000713 rtc::scoped_refptr<MockStatsObserver> observer(
714 new rtc::RefCountedObject<MockStatsObserver>());
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +0000715 if (!pc_->GetStats(
716 observer, track, PeerConnectionInterface::kStatsOutputLevelStandard))
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000717 return false;
718 EXPECT_TRUE_WAIT(observer->called(), kTimeout);
719 return observer->called();
720 }
721
722 void InitiateCall() {
723 CreatePeerConnection();
724 // Create a local stream with audio&video tracks.
725 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
726 CreateOfferReceiveAnswer();
727 }
728
729 // Verify that RTP Header extensions has been negotiated for audio and video.
730 void VerifyRemoteRtpHeaderExtensions() {
731 const cricket::MediaContentDescription* desc =
732 cricket::GetFirstAudioContentDescription(
733 pc_->remote_description()->description());
734 ASSERT_TRUE(desc != NULL);
735 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
736
737 desc = cricket::GetFirstVideoContentDescription(
738 pc_->remote_description()->description());
739 ASSERT_TRUE(desc != NULL);
740 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
741 }
742
743 void CreateOfferAsRemoteDescription() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000744 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700745 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 std::string sdp;
747 EXPECT_TRUE(offer->ToString(&sdp));
748 SessionDescriptionInterface* remote_offer =
749 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
750 sdp, NULL);
751 EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
752 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
753 }
754
deadbeefab9b2d12015-10-14 11:33:11 -0700755 void CreateAndSetRemoteOffer(const std::string& sdp) {
756 SessionDescriptionInterface* remote_offer =
757 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
758 sdp, nullptr);
759 EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
760 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
761 }
762
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000763 void CreateAnswerAsLocalDescription() {
764 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -0700765 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766
767 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
768 // audio codec change, even if the parameter has nothing to do with
769 // receiving. Not all parameters are serialized to SDP.
770 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
771 // the SessionDescription, it is necessary to do that here to in order to
772 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
773 // https://code.google.com/p/webrtc/issues/detail?id=1356
774 std::string sdp;
775 EXPECT_TRUE(answer->ToString(&sdp));
776 SessionDescriptionInterface* new_answer =
777 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
778 sdp, NULL);
779 EXPECT_TRUE(DoSetLocalDescription(new_answer));
780 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
781 }
782
783 void CreatePrAnswerAsLocalDescription() {
784 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -0700785 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786
787 std::string sdp;
788 EXPECT_TRUE(answer->ToString(&sdp));
789 SessionDescriptionInterface* pr_answer =
790 webrtc::CreateSessionDescription(SessionDescriptionInterface::kPrAnswer,
791 sdp, NULL);
792 EXPECT_TRUE(DoSetLocalDescription(pr_answer));
793 EXPECT_EQ(PeerConnectionInterface::kHaveLocalPrAnswer, observer_.state_);
794 }
795
796 void CreateOfferReceiveAnswer() {
797 CreateOfferAsLocalDescription();
798 std::string sdp;
799 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
800 CreateAnswerAsRemoteDescription(sdp);
801 }
802
803 void CreateOfferAsLocalDescription() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000804 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700805 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
807 // audio codec change, even if the parameter has nothing to do with
808 // receiving. Not all parameters are serialized to SDP.
809 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
810 // the SessionDescription, it is necessary to do that here to in order to
811 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
812 // https://code.google.com/p/webrtc/issues/detail?id=1356
813 std::string sdp;
814 EXPECT_TRUE(offer->ToString(&sdp));
815 SessionDescriptionInterface* new_offer =
816 webrtc::CreateSessionDescription(
817 SessionDescriptionInterface::kOffer,
818 sdp, NULL);
819
820 EXPECT_TRUE(DoSetLocalDescription(new_offer));
821 EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer, observer_.state_);
mallinath@webrtc.org68cbd012014-01-22 00:16:46 +0000822 // Wait for the ice_complete message, so that SDP will have candidates.
823 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000824 }
825
deadbeefab9b2d12015-10-14 11:33:11 -0700826 void CreateAnswerAsRemoteDescription(const std::string& sdp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000827 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
828 SessionDescriptionInterface::kAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700829 EXPECT_TRUE(answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000830 EXPECT_TRUE(DoSetRemoteDescription(answer));
831 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
832 }
833
deadbeefab9b2d12015-10-14 11:33:11 -0700834 void CreatePrAnswerAndAnswerAsRemoteDescription(const std::string& sdp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 webrtc::JsepSessionDescription* pr_answer =
836 new webrtc::JsepSessionDescription(
837 SessionDescriptionInterface::kPrAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700838 EXPECT_TRUE(pr_answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000839 EXPECT_TRUE(DoSetRemoteDescription(pr_answer));
840 EXPECT_EQ(PeerConnectionInterface::kHaveRemotePrAnswer, observer_.state_);
841 webrtc::JsepSessionDescription* answer =
842 new webrtc::JsepSessionDescription(
843 SessionDescriptionInterface::kAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700844 EXPECT_TRUE(answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000845 EXPECT_TRUE(DoSetRemoteDescription(answer));
846 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
847 }
848
849 // Help function used for waiting until a the last signaled remote stream has
850 // the same label as |stream_label|. In a few of the tests in this file we
851 // answer with the same session description as we offer and thus we can
852 // check if OnAddStream have been called with the same stream as we offer to
853 // send.
854 void WaitAndVerifyOnAddStream(const std::string& stream_label) {
855 EXPECT_EQ_WAIT(stream_label, observer_.GetLastAddedStreamLabel(), kTimeout);
856 }
857
858 // Creates an offer and applies it as a local session description.
859 // Creates an answer with the same SDP an the offer but removes all lines
860 // that start with a:ssrc"
861 void CreateOfferReceiveAnswerWithoutSsrc() {
862 CreateOfferAsLocalDescription();
863 std::string sdp;
864 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
865 SetSsrcToZero(&sdp);
866 CreateAnswerAsRemoteDescription(sdp);
867 }
868
deadbeefab9b2d12015-10-14 11:33:11 -0700869 // This function creates a MediaStream with label kStreams[0] and
870 // |number_of_audio_tracks| and |number_of_video_tracks| tracks and the
871 // corresponding SessionDescriptionInterface. The SessionDescriptionInterface
872 // is returned in |desc| and the MediaStream is stored in
873 // |reference_collection_|
874 void CreateSessionDescriptionAndReference(
875 size_t number_of_audio_tracks,
876 size_t number_of_video_tracks,
877 SessionDescriptionInterface** desc) {
878 ASSERT_TRUE(desc != nullptr);
879 ASSERT_LE(number_of_audio_tracks, 2u);
880 ASSERT_LE(number_of_video_tracks, 2u);
881
882 reference_collection_ = StreamCollection::Create();
883 std::string sdp_ms1 = std::string(kSdpStringInit);
884
885 std::string mediastream_label = kStreams[0];
886
887 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
888 webrtc::MediaStream::Create(mediastream_label));
889 reference_collection_->AddStream(stream);
890
891 if (number_of_audio_tracks > 0) {
892 sdp_ms1 += std::string(kSdpStringAudio);
893 sdp_ms1 += std::string(kSdpStringMs1Audio0);
894 AddAudioTrack(kAudioTracks[0], stream);
895 }
896 if (number_of_audio_tracks > 1) {
897 sdp_ms1 += kSdpStringMs1Audio1;
898 AddAudioTrack(kAudioTracks[1], stream);
899 }
900
901 if (number_of_video_tracks > 0) {
902 sdp_ms1 += std::string(kSdpStringVideo);
903 sdp_ms1 += std::string(kSdpStringMs1Video0);
904 AddVideoTrack(kVideoTracks[0], stream);
905 }
906 if (number_of_video_tracks > 1) {
907 sdp_ms1 += kSdpStringMs1Video1;
908 AddVideoTrack(kVideoTracks[1], stream);
909 }
910
911 *desc = webrtc::CreateSessionDescription(
912 SessionDescriptionInterface::kOffer, sdp_ms1, nullptr);
913 }
914
915 void AddAudioTrack(const std::string& track_id,
916 MediaStreamInterface* stream) {
917 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
918 webrtc::AudioTrack::Create(track_id, nullptr));
919 ASSERT_TRUE(stream->AddTrack(audio_track));
920 }
921
922 void AddVideoTrack(const std::string& track_id,
923 MediaStreamInterface* stream) {
924 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
925 webrtc::VideoTrack::Create(track_id, nullptr));
926 ASSERT_TRUE(stream->AddTrack(video_track));
927 }
928
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000929 scoped_refptr<FakePortAllocatorFactory> port_allocator_factory_;
930 scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
931 scoped_refptr<PeerConnectionInterface> pc_;
932 MockPeerConnectionObserver observer_;
deadbeefab9b2d12015-10-14 11:33:11 -0700933 rtc::scoped_refptr<StreamCollection> reference_collection_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934};
935
936TEST_F(PeerConnectionInterfaceTest,
937 CreatePeerConnectionWithDifferentConfigurations) {
938 CreatePeerConnectionWithDifferentConfigurations();
939}
940
941TEST_F(PeerConnectionInterfaceTest, AddStreams) {
942 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -0700943 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 AddVoiceStream(kStreamLabel2);
945 ASSERT_EQ(2u, pc_->local_streams()->count());
946
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000947 // Test we can add multiple local streams to one peerconnection.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000948 scoped_refptr<MediaStreamInterface> stream(
949 pc_factory_->CreateLocalMediaStream(kStreamLabel3));
950 scoped_refptr<AudioTrackInterface> audio_track(
951 pc_factory_->CreateAudioTrack(
952 kStreamLabel3, static_cast<AudioSourceInterface*>(NULL)));
953 stream->AddTrack(audio_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000954 EXPECT_TRUE(pc_->AddStream(stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000955 EXPECT_EQ(3u, pc_->local_streams()->count());
956
957 // Remove the third stream.
958 pc_->RemoveStream(pc_->local_streams()->at(2));
959 EXPECT_EQ(2u, pc_->local_streams()->count());
960
961 // Remove the second stream.
962 pc_->RemoveStream(pc_->local_streams()->at(1));
963 EXPECT_EQ(1u, pc_->local_streams()->count());
964
965 // Remove the first stream.
966 pc_->RemoveStream(pc_->local_streams()->at(0));
967 EXPECT_EQ(0u, pc_->local_streams()->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000968}
969
deadbeefab9b2d12015-10-14 11:33:11 -0700970// Test that the created offer includes streams we added.
971TEST_F(PeerConnectionInterfaceTest, AddedStreamsPresentInOffer) {
972 CreatePeerConnection();
973 AddAudioVideoStream(kStreamLabel1, "audio_track", "video_track");
974 scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700975 ASSERT_TRUE(DoCreateOffer(offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -0700976
977 const cricket::ContentInfo* audio_content =
978 cricket::GetFirstAudioContent(offer->description());
979 const cricket::AudioContentDescription* audio_desc =
980 static_cast<const cricket::AudioContentDescription*>(
981 audio_content->description);
982 EXPECT_TRUE(
983 ContainsTrack(audio_desc->streams(), kStreamLabel1, "audio_track"));
984
985 const cricket::ContentInfo* video_content =
986 cricket::GetFirstVideoContent(offer->description());
987 const cricket::VideoContentDescription* video_desc =
988 static_cast<const cricket::VideoContentDescription*>(
989 video_content->description);
990 EXPECT_TRUE(
991 ContainsTrack(video_desc->streams(), kStreamLabel1, "video_track"));
992
993 // Add another stream and ensure the offer includes both the old and new
994 // streams.
995 AddAudioVideoStream(kStreamLabel2, "audio_track2", "video_track2");
deadbeefc80741f2015-10-22 13:14:45 -0700996 ASSERT_TRUE(DoCreateOffer(offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -0700997
998 audio_content = cricket::GetFirstAudioContent(offer->description());
999 audio_desc = static_cast<const cricket::AudioContentDescription*>(
1000 audio_content->description);
1001 EXPECT_TRUE(
1002 ContainsTrack(audio_desc->streams(), kStreamLabel1, "audio_track"));
1003 EXPECT_TRUE(
1004 ContainsTrack(audio_desc->streams(), kStreamLabel2, "audio_track2"));
1005
1006 video_content = cricket::GetFirstVideoContent(offer->description());
1007 video_desc = static_cast<const cricket::VideoContentDescription*>(
1008 video_content->description);
1009 EXPECT_TRUE(
1010 ContainsTrack(video_desc->streams(), kStreamLabel1, "video_track"));
1011 EXPECT_TRUE(
1012 ContainsTrack(video_desc->streams(), kStreamLabel2, "video_track2"));
1013}
1014
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001015TEST_F(PeerConnectionInterfaceTest, RemoveStream) {
1016 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001017 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 ASSERT_EQ(1u, pc_->local_streams()->count());
1019 pc_->RemoveStream(pc_->local_streams()->at(0));
1020 EXPECT_EQ(0u, pc_->local_streams()->count());
1021}
1022
1023TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) {
1024 InitiateCall();
1025 WaitAndVerifyOnAddStream(kStreamLabel1);
1026 VerifyRemoteRtpHeaderExtensions();
1027}
1028
1029TEST_F(PeerConnectionInterfaceTest, CreateOfferReceivePrAnswerAndAnswer) {
1030 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001031 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001032 CreateOfferAsLocalDescription();
1033 std::string offer;
1034 EXPECT_TRUE(pc_->local_description()->ToString(&offer));
1035 CreatePrAnswerAndAnswerAsRemoteDescription(offer);
1036 WaitAndVerifyOnAddStream(kStreamLabel1);
1037}
1038
1039TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreateAnswer) {
1040 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001041 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001042
1043 CreateOfferAsRemoteDescription();
1044 CreateAnswerAsLocalDescription();
1045
1046 WaitAndVerifyOnAddStream(kStreamLabel1);
1047}
1048
1049TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreatePrAnswerAndAnswer) {
1050 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001051 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001052
1053 CreateOfferAsRemoteDescription();
1054 CreatePrAnswerAsLocalDescription();
1055 CreateAnswerAsLocalDescription();
1056
1057 WaitAndVerifyOnAddStream(kStreamLabel1);
1058}
1059
1060TEST_F(PeerConnectionInterfaceTest, Renegotiate) {
1061 InitiateCall();
1062 ASSERT_EQ(1u, pc_->remote_streams()->count());
1063 pc_->RemoveStream(pc_->local_streams()->at(0));
1064 CreateOfferReceiveAnswer();
1065 EXPECT_EQ(0u, pc_->remote_streams()->count());
deadbeefab9b2d12015-10-14 11:33:11 -07001066 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 CreateOfferReceiveAnswer();
1068}
1069
1070// Tests that after negotiating an audio only call, the respondent can perform a
1071// renegotiation that removes the audio stream.
1072TEST_F(PeerConnectionInterfaceTest, RenegotiateAudioOnly) {
1073 CreatePeerConnection();
1074 AddVoiceStream(kStreamLabel1);
1075 CreateOfferAsRemoteDescription();
1076 CreateAnswerAsLocalDescription();
1077
1078 ASSERT_EQ(1u, pc_->remote_streams()->count());
1079 pc_->RemoveStream(pc_->local_streams()->at(0));
1080 CreateOfferReceiveAnswer();
1081 EXPECT_EQ(0u, pc_->remote_streams()->count());
1082}
1083
1084// Test that candidates are generated and that we can parse our own candidates.
1085TEST_F(PeerConnectionInterfaceTest, IceCandidates) {
1086 CreatePeerConnection();
1087
1088 EXPECT_FALSE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
1089 // SetRemoteDescription takes ownership of offer.
1090 SessionDescriptionInterface* offer = NULL;
deadbeefab9b2d12015-10-14 11:33:11 -07001091 AddVideoStream(kStreamLabel1);
deadbeefc80741f2015-10-22 13:14:45 -07001092 EXPECT_TRUE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093 EXPECT_TRUE(DoSetRemoteDescription(offer));
1094
1095 // SetLocalDescription takes ownership of answer.
1096 SessionDescriptionInterface* answer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001097 EXPECT_TRUE(DoCreateAnswer(&answer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001098 EXPECT_TRUE(DoSetLocalDescription(answer));
1099
1100 EXPECT_TRUE_WAIT(observer_.last_candidate_.get() != NULL, kTimeout);
1101 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
1102
1103 EXPECT_TRUE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
1104}
1105
deadbeefab9b2d12015-10-14 11:33:11 -07001106// Test that CreateOffer and CreateAnswer will fail if the track labels are
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001107// not unique.
1108TEST_F(PeerConnectionInterfaceTest, CreateOfferAnswerWithInvalidStream) {
1109 CreatePeerConnection();
1110 // Create a regular offer for the CreateAnswer test later.
1111 SessionDescriptionInterface* offer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001112 EXPECT_TRUE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001113 EXPECT_TRUE(offer != NULL);
1114 delete offer;
1115 offer = NULL;
1116
1117 // Create a local stream with audio&video tracks having same label.
1118 AddAudioVideoStream(kStreamLabel1, "track_label", "track_label");
1119
1120 // Test CreateOffer
deadbeefc80741f2015-10-22 13:14:45 -07001121 EXPECT_FALSE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001122
1123 // Test CreateAnswer
1124 SessionDescriptionInterface* answer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001125 EXPECT_FALSE(DoCreateAnswer(&answer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001126}
1127
1128// Test that we will get different SSRCs for each tracks in the offer and answer
1129// we created.
1130TEST_F(PeerConnectionInterfaceTest, SsrcInOfferAnswer) {
1131 CreatePeerConnection();
1132 // Create a local stream with audio&video tracks having different labels.
1133 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1134
1135 // Test CreateOffer
1136 scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -07001137 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001138 int audio_ssrc = 0;
1139 int video_ssrc = 0;
1140 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(offer->description()),
1141 &audio_ssrc));
1142 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(offer->description()),
1143 &video_ssrc));
1144 EXPECT_NE(audio_ssrc, video_ssrc);
1145
1146 // Test CreateAnswer
1147 EXPECT_TRUE(DoSetRemoteDescription(offer.release()));
1148 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -07001149 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001150 audio_ssrc = 0;
1151 video_ssrc = 0;
1152 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(answer->description()),
1153 &audio_ssrc));
1154 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(answer->description()),
1155 &video_ssrc));
1156 EXPECT_NE(audio_ssrc, video_ssrc);
1157}
1158
deadbeefeb459812015-12-15 19:24:43 -08001159// Test that it's possible to call AddTrack on a MediaStream after adding
1160// the stream to a PeerConnection.
1161// TODO(deadbeef): Remove this test once this behavior is no longer supported.
1162TEST_F(PeerConnectionInterfaceTest, AddTrackAfterAddStream) {
1163 CreatePeerConnection();
1164 // Create audio stream and add to PeerConnection.
1165 AddVoiceStream(kStreamLabel1);
1166 MediaStreamInterface* stream = pc_->local_streams()->at(0);
1167
1168 // Add video track to the audio-only stream.
1169 scoped_refptr<VideoTrackInterface> video_track(
1170 pc_factory_->CreateVideoTrack("video_label", nullptr));
1171 stream->AddTrack(video_track.get());
1172
1173 scoped_ptr<SessionDescriptionInterface> offer;
1174 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1175
1176 const cricket::MediaContentDescription* video_desc =
1177 cricket::GetFirstVideoContentDescription(offer->description());
1178 EXPECT_TRUE(video_desc != nullptr);
1179}
1180
1181// Test that it's possible to call RemoveTrack on a MediaStream after adding
1182// the stream to a PeerConnection.
1183// TODO(deadbeef): Remove this test once this behavior is no longer supported.
1184TEST_F(PeerConnectionInterfaceTest, RemoveTrackAfterAddStream) {
1185 CreatePeerConnection();
1186 // Create audio/video stream and add to PeerConnection.
1187 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1188 MediaStreamInterface* stream = pc_->local_streams()->at(0);
1189
1190 // Remove the video track.
1191 stream->RemoveTrack(stream->GetVideoTracks()[0]);
1192
1193 scoped_ptr<SessionDescriptionInterface> offer;
1194 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1195
1196 const cricket::MediaContentDescription* video_desc =
1197 cricket::GetFirstVideoContentDescription(offer->description());
1198 EXPECT_TRUE(video_desc == nullptr);
1199}
1200
deadbeefbd7d8f72015-12-18 16:58:44 -08001201// Test creating a sender with a stream ID, and ensure the ID is populated
1202// in the offer.
1203TEST_F(PeerConnectionInterfaceTest, CreateSenderWithStream) {
1204 CreatePeerConnection();
1205 pc_->CreateSender("video", kStreamLabel1);
1206
1207 scoped_ptr<SessionDescriptionInterface> offer;
1208 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1209
1210 const cricket::MediaContentDescription* video_desc =
1211 cricket::GetFirstVideoContentDescription(offer->description());
1212 ASSERT_TRUE(video_desc != nullptr);
1213 ASSERT_EQ(1u, video_desc->streams().size());
1214 EXPECT_EQ(kStreamLabel1, video_desc->streams()[0].sync_label);
1215}
1216
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001217// Test that we can specify a certain track that we want statistics about.
1218TEST_F(PeerConnectionInterfaceTest, GetStatsForSpecificTrack) {
1219 InitiateCall();
1220 ASSERT_LT(0u, pc_->remote_streams()->count());
1221 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetAudioTracks().size());
1222 scoped_refptr<MediaStreamTrackInterface> remote_audio =
1223 pc_->remote_streams()->at(0)->GetAudioTracks()[0];
1224 EXPECT_TRUE(DoGetStats(remote_audio));
1225
1226 // Remove the stream. Since we are sending to our selves the local
1227 // and the remote stream is the same.
1228 pc_->RemoveStream(pc_->local_streams()->at(0));
1229 // Do a re-negotiation.
1230 CreateOfferReceiveAnswer();
1231
1232 ASSERT_EQ(0u, pc_->remote_streams()->count());
1233
1234 // Test that we still can get statistics for the old track. Even if it is not
1235 // sent any longer.
1236 EXPECT_TRUE(DoGetStats(remote_audio));
1237}
1238
1239// Test that we can get stats on a video track.
1240TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
1241 InitiateCall();
1242 ASSERT_LT(0u, pc_->remote_streams()->count());
1243 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetVideoTracks().size());
1244 scoped_refptr<MediaStreamTrackInterface> remote_video =
1245 pc_->remote_streams()->at(0)->GetVideoTracks()[0];
1246 EXPECT_TRUE(DoGetStats(remote_video));
1247}
1248
1249// Test that we don't get statistics for an invalid track.
tommi@webrtc.org908f57e2014-07-21 11:44:39 +00001250// TODO(tommi): Fix this test. DoGetStats will return true
1251// for the unknown track (since GetStats is async), but no
1252// data is returned for the track.
1253TEST_F(PeerConnectionInterfaceTest, DISABLED_GetStatsForInvalidTrack) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001254 InitiateCall();
1255 scoped_refptr<AudioTrackInterface> unknown_audio_track(
1256 pc_factory_->CreateAudioTrack("unknown track", NULL));
1257 EXPECT_FALSE(DoGetStats(unknown_audio_track));
1258}
1259
1260// This test setup two RTP data channels in loop back.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001261TEST_F(PeerConnectionInterfaceTest, TestDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001262 FakeConstraints constraints;
1263 constraints.SetAllowRtpDataChannels();
1264 CreatePeerConnection(&constraints);
1265 scoped_refptr<DataChannelInterface> data1 =
1266 pc_->CreateDataChannel("test1", NULL);
1267 scoped_refptr<DataChannelInterface> data2 =
1268 pc_->CreateDataChannel("test2", NULL);
1269 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001270 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001271 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001272 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001273 new MockDataChannelObserver(data2));
1274
1275 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1276 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1277 std::string data_to_send1 = "testing testing";
1278 std::string data_to_send2 = "testing something else";
1279 EXPECT_FALSE(data1->Send(DataBuffer(data_to_send1)));
1280
1281 CreateOfferReceiveAnswer();
1282 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1283 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1284
1285 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1286 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1287 EXPECT_TRUE(data1->Send(DataBuffer(data_to_send1)));
1288 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1289
1290 EXPECT_EQ_WAIT(data_to_send1, observer1->last_message(), kTimeout);
1291 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1292
1293 data1->Close();
1294 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1295 CreateOfferReceiveAnswer();
1296 EXPECT_FALSE(observer1->IsOpen());
1297 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1298 EXPECT_TRUE(observer2->IsOpen());
1299
1300 data_to_send2 = "testing something else again";
1301 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1302
1303 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1304}
1305
1306// This test verifies that sendnig binary data over RTP data channels should
1307// fail.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001308TEST_F(PeerConnectionInterfaceTest, TestSendBinaryOnRtpDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001309 FakeConstraints constraints;
1310 constraints.SetAllowRtpDataChannels();
1311 CreatePeerConnection(&constraints);
1312 scoped_refptr<DataChannelInterface> data1 =
1313 pc_->CreateDataChannel("test1", NULL);
1314 scoped_refptr<DataChannelInterface> data2 =
1315 pc_->CreateDataChannel("test2", NULL);
1316 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001317 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001319 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001320 new MockDataChannelObserver(data2));
1321
1322 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1323 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1324
1325 CreateOfferReceiveAnswer();
1326 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1327 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1328
1329 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1330 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1331
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001332 rtc::Buffer buffer("test", 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001333 EXPECT_FALSE(data1->Send(DataBuffer(buffer, true)));
1334}
1335
1336// This test setup a RTP data channels in loop back and test that a channel is
1337// opened even if the remote end answer with a zero SSRC.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001338TEST_F(PeerConnectionInterfaceTest, TestSendOnlyDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001339 FakeConstraints constraints;
1340 constraints.SetAllowRtpDataChannels();
1341 CreatePeerConnection(&constraints);
1342 scoped_refptr<DataChannelInterface> data1 =
1343 pc_->CreateDataChannel("test1", NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001344 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345 new MockDataChannelObserver(data1));
1346
1347 CreateOfferReceiveAnswerWithoutSsrc();
1348
1349 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1350
1351 data1->Close();
1352 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1353 CreateOfferReceiveAnswerWithoutSsrc();
1354 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1355 EXPECT_FALSE(observer1->IsOpen());
1356}
1357
1358// This test that if a data channel is added in an answer a receive only channel
1359// channel is created.
1360TEST_F(PeerConnectionInterfaceTest, TestReceiveOnlyDataChannel) {
1361 FakeConstraints constraints;
1362 constraints.SetAllowRtpDataChannels();
1363 CreatePeerConnection(&constraints);
1364
1365 std::string offer_label = "offer_channel";
1366 scoped_refptr<DataChannelInterface> offer_channel =
1367 pc_->CreateDataChannel(offer_label, NULL);
1368
1369 CreateOfferAsLocalDescription();
1370
1371 // Replace the data channel label in the offer and apply it as an answer.
1372 std::string receive_label = "answer_channel";
1373 std::string sdp;
1374 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001375 rtc::replace_substrs(offer_label.c_str(), offer_label.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001376 receive_label.c_str(), receive_label.length(),
1377 &sdp);
1378 CreateAnswerAsRemoteDescription(sdp);
1379
1380 // Verify that a new incoming data channel has been created and that
1381 // it is open but can't we written to.
1382 ASSERT_TRUE(observer_.last_datachannel_ != NULL);
1383 DataChannelInterface* received_channel = observer_.last_datachannel_;
1384 EXPECT_EQ(DataChannelInterface::kConnecting, received_channel->state());
1385 EXPECT_EQ(receive_label, received_channel->label());
1386 EXPECT_FALSE(received_channel->Send(DataBuffer("something")));
1387
1388 // Verify that the channel we initially offered has been rejected.
1389 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1390
1391 // Do another offer / answer exchange and verify that the data channel is
1392 // opened.
1393 CreateOfferReceiveAnswer();
1394 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, received_channel->state(),
1395 kTimeout);
1396}
1397
1398// This test that no data channel is returned if a reliable channel is
1399// requested.
1400// TODO(perkj): Remove this test once reliable channels are implemented.
1401TEST_F(PeerConnectionInterfaceTest, CreateReliableRtpDataChannelShouldFail) {
1402 FakeConstraints constraints;
1403 constraints.SetAllowRtpDataChannels();
1404 CreatePeerConnection(&constraints);
1405
1406 std::string label = "test";
1407 webrtc::DataChannelInit config;
1408 config.reliable = true;
1409 scoped_refptr<DataChannelInterface> channel =
1410 pc_->CreateDataChannel(label, &config);
1411 EXPECT_TRUE(channel == NULL);
1412}
1413
deadbeefab9b2d12015-10-14 11:33:11 -07001414// Verifies that duplicated label is not allowed for RTP data channel.
1415TEST_F(PeerConnectionInterfaceTest, RtpDuplicatedLabelNotAllowed) {
1416 FakeConstraints constraints;
1417 constraints.SetAllowRtpDataChannels();
1418 CreatePeerConnection(&constraints);
1419
1420 std::string label = "test";
1421 scoped_refptr<DataChannelInterface> channel =
1422 pc_->CreateDataChannel(label, nullptr);
1423 EXPECT_NE(channel, nullptr);
1424
1425 scoped_refptr<DataChannelInterface> dup_channel =
1426 pc_->CreateDataChannel(label, nullptr);
1427 EXPECT_EQ(dup_channel, nullptr);
1428}
1429
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001430// This tests that a SCTP data channel is returned using different
1431// DataChannelInit configurations.
1432TEST_F(PeerConnectionInterfaceTest, CreateSctpDataChannel) {
1433 FakeConstraints constraints;
1434 constraints.SetAllowDtlsSctpDataChannels();
1435 CreatePeerConnection(&constraints);
1436
1437 webrtc::DataChannelInit config;
1438
1439 scoped_refptr<DataChannelInterface> channel =
1440 pc_->CreateDataChannel("1", &config);
1441 EXPECT_TRUE(channel != NULL);
1442 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001443 EXPECT_TRUE(observer_.renegotiation_needed_);
1444 observer_.renegotiation_needed_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445
1446 config.ordered = false;
1447 channel = pc_->CreateDataChannel("2", &config);
1448 EXPECT_TRUE(channel != NULL);
1449 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001450 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001451
1452 config.ordered = true;
1453 config.maxRetransmits = 0;
1454 channel = pc_->CreateDataChannel("3", &config);
1455 EXPECT_TRUE(channel != NULL);
1456 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001457 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001458
1459 config.maxRetransmits = -1;
1460 config.maxRetransmitTime = 0;
1461 channel = pc_->CreateDataChannel("4", &config);
1462 EXPECT_TRUE(channel != NULL);
1463 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001464 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001465}
1466
1467// This tests that no data channel is returned if both maxRetransmits and
1468// maxRetransmitTime are set for SCTP data channels.
1469TEST_F(PeerConnectionInterfaceTest,
1470 CreateSctpDataChannelShouldFailForInvalidConfig) {
1471 FakeConstraints constraints;
1472 constraints.SetAllowDtlsSctpDataChannels();
1473 CreatePeerConnection(&constraints);
1474
1475 std::string label = "test";
1476 webrtc::DataChannelInit config;
1477 config.maxRetransmits = 0;
1478 config.maxRetransmitTime = 0;
1479
1480 scoped_refptr<DataChannelInterface> channel =
1481 pc_->CreateDataChannel(label, &config);
1482 EXPECT_TRUE(channel == NULL);
1483}
1484
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485// The test verifies that creating a SCTP data channel with an id already in use
1486// or out of range should fail.
1487TEST_F(PeerConnectionInterfaceTest,
1488 CreateSctpDataChannelWithInvalidIdShouldFail) {
1489 FakeConstraints constraints;
1490 constraints.SetAllowDtlsSctpDataChannels();
1491 CreatePeerConnection(&constraints);
1492
1493 webrtc::DataChannelInit config;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001494 scoped_refptr<DataChannelInterface> channel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001496 config.id = 1;
1497 channel = pc_->CreateDataChannel("1", &config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001498 EXPECT_TRUE(channel != NULL);
1499 EXPECT_EQ(1, channel->id());
1500
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001501 channel = pc_->CreateDataChannel("x", &config);
1502 EXPECT_TRUE(channel == NULL);
1503
1504 config.id = cricket::kMaxSctpSid;
1505 channel = pc_->CreateDataChannel("max", &config);
1506 EXPECT_TRUE(channel != NULL);
1507 EXPECT_EQ(config.id, channel->id());
1508
1509 config.id = cricket::kMaxSctpSid + 1;
1510 channel = pc_->CreateDataChannel("x", &config);
1511 EXPECT_TRUE(channel == NULL);
1512}
1513
deadbeefab9b2d12015-10-14 11:33:11 -07001514// Verifies that duplicated label is allowed for SCTP data channel.
1515TEST_F(PeerConnectionInterfaceTest, SctpDuplicatedLabelAllowed) {
1516 FakeConstraints constraints;
1517 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1518 true);
1519 CreatePeerConnection(&constraints);
1520
1521 std::string label = "test";
1522 scoped_refptr<DataChannelInterface> channel =
1523 pc_->CreateDataChannel(label, nullptr);
1524 EXPECT_NE(channel, nullptr);
1525
1526 scoped_refptr<DataChannelInterface> dup_channel =
1527 pc_->CreateDataChannel(label, nullptr);
1528 EXPECT_NE(dup_channel, nullptr);
1529}
1530
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001531// This test verifies that OnRenegotiationNeeded is fired for every new RTP
1532// DataChannel.
1533TEST_F(PeerConnectionInterfaceTest, RenegotiationNeededForNewRtpDataChannel) {
1534 FakeConstraints constraints;
1535 constraints.SetAllowRtpDataChannels();
1536 CreatePeerConnection(&constraints);
1537
1538 scoped_refptr<DataChannelInterface> dc1 =
1539 pc_->CreateDataChannel("test1", NULL);
1540 EXPECT_TRUE(observer_.renegotiation_needed_);
1541 observer_.renegotiation_needed_ = false;
1542
1543 scoped_refptr<DataChannelInterface> dc2 =
1544 pc_->CreateDataChannel("test2", NULL);
1545 EXPECT_TRUE(observer_.renegotiation_needed_);
1546}
1547
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001548// This test that a data channel closes when a PeerConnection is deleted/closed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001549TEST_F(PeerConnectionInterfaceTest, DataChannelCloseWhenPeerConnectionClose) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550 FakeConstraints constraints;
1551 constraints.SetAllowRtpDataChannels();
1552 CreatePeerConnection(&constraints);
1553
1554 scoped_refptr<DataChannelInterface> data1 =
1555 pc_->CreateDataChannel("test1", NULL);
1556 scoped_refptr<DataChannelInterface> data2 =
1557 pc_->CreateDataChannel("test2", NULL);
1558 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001559 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001560 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001561 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001562 new MockDataChannelObserver(data2));
1563
1564 CreateOfferReceiveAnswer();
1565 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1566 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1567
1568 ReleasePeerConnection();
1569 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1570 EXPECT_EQ(DataChannelInterface::kClosed, data2->state());
1571}
1572
1573// This test that data channels can be rejected in an answer.
1574TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
1575 FakeConstraints constraints;
1576 constraints.SetAllowRtpDataChannels();
1577 CreatePeerConnection(&constraints);
1578
1579 scoped_refptr<DataChannelInterface> offer_channel(
1580 pc_->CreateDataChannel("offer_channel", NULL));
1581
1582 CreateOfferAsLocalDescription();
1583
1584 // Create an answer where the m-line for data channels are rejected.
1585 std::string sdp;
1586 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
1587 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
1588 SessionDescriptionInterface::kAnswer);
1589 EXPECT_TRUE(answer->Initialize(sdp, NULL));
1590 cricket::ContentInfo* data_info =
1591 answer->description()->GetContentByName("data");
1592 data_info->rejected = true;
1593
1594 DoSetRemoteDescription(answer);
1595 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1596}
1597
1598// Test that we can create a session description from an SDP string from
1599// FireFox, use it as a remote session description, generate an answer and use
1600// the answer as a local description.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001601TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001602 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603 FakeConstraints constraints;
1604 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1605 true);
1606 CreatePeerConnection(&constraints);
1607 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1608 SessionDescriptionInterface* desc =
1609 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001610 webrtc::kFireFoxSdpOffer, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611 EXPECT_TRUE(DoSetSessionDescription(desc, false));
1612 CreateAnswerAsLocalDescription();
1613 ASSERT_TRUE(pc_->local_description() != NULL);
1614 ASSERT_TRUE(pc_->remote_description() != NULL);
1615
1616 const cricket::ContentInfo* content =
1617 cricket::GetFirstAudioContent(pc_->local_description()->description());
1618 ASSERT_TRUE(content != NULL);
1619 EXPECT_FALSE(content->rejected);
1620
1621 content =
1622 cricket::GetFirstVideoContent(pc_->local_description()->description());
1623 ASSERT_TRUE(content != NULL);
1624 EXPECT_FALSE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001625#ifdef HAVE_SCTP
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 content =
1627 cricket::GetFirstDataContent(pc_->local_description()->description());
1628 ASSERT_TRUE(content != NULL);
1629 EXPECT_TRUE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001630#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631}
1632
1633// Test that we can create an audio only offer and receive an answer with a
1634// limited set of audio codecs and receive an updated offer with more audio
1635// codecs, where the added codecs are not supported.
1636TEST_F(PeerConnectionInterfaceTest, ReceiveUpdatedAudioOfferWithBadCodecs) {
1637 CreatePeerConnection();
1638 AddVoiceStream("audio_label");
1639 CreateOfferAsLocalDescription();
1640
1641 SessionDescriptionInterface* answer =
1642 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
jbauchfabe2c92015-07-16 13:43:14 -07001643 webrtc::kAudioSdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644 EXPECT_TRUE(DoSetSessionDescription(answer, false));
1645
1646 SessionDescriptionInterface* updated_offer =
1647 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001648 webrtc::kAudioSdpWithUnsupportedCodecs,
1649 nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 EXPECT_TRUE(DoSetSessionDescription(updated_offer, false));
1651 CreateAnswerAsLocalDescription();
1652}
1653
deadbeefc80741f2015-10-22 13:14:45 -07001654// Test that if we're receiving (but not sending) a track, subsequent offers
1655// will have m-lines with a=recvonly.
1656TEST_F(PeerConnectionInterfaceTest, CreateSubsequentRecvOnlyOffer) {
1657 FakeConstraints constraints;
1658 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1659 true);
1660 CreatePeerConnection(&constraints);
1661 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1662 CreateAnswerAsLocalDescription();
1663
1664 // At this point we should be receiving stream 1, but not sending anything.
1665 // A new offer should be recvonly.
1666 SessionDescriptionInterface* offer;
1667 DoCreateOffer(&offer, nullptr);
1668
1669 const cricket::ContentInfo* video_content =
1670 cricket::GetFirstVideoContent(offer->description());
1671 const cricket::VideoContentDescription* video_desc =
1672 static_cast<const cricket::VideoContentDescription*>(
1673 video_content->description);
1674 ASSERT_EQ(cricket::MD_RECVONLY, video_desc->direction());
1675
1676 const cricket::ContentInfo* audio_content =
1677 cricket::GetFirstAudioContent(offer->description());
1678 const cricket::AudioContentDescription* audio_desc =
1679 static_cast<const cricket::AudioContentDescription*>(
1680 audio_content->description);
1681 ASSERT_EQ(cricket::MD_RECVONLY, audio_desc->direction());
1682}
1683
1684// Test that if we're receiving (but not sending) a track, and the
1685// offerToReceiveVideo/offerToReceiveAudio constraints are explicitly set to
1686// false, the generated m-lines will be a=inactive.
1687TEST_F(PeerConnectionInterfaceTest, CreateSubsequentInactiveOffer) {
1688 FakeConstraints constraints;
1689 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1690 true);
1691 CreatePeerConnection(&constraints);
1692 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1693 CreateAnswerAsLocalDescription();
1694
1695 // At this point we should be receiving stream 1, but not sending anything.
1696 // A new offer would be recvonly, but we'll set the "no receive" constraints
1697 // to make it inactive.
1698 SessionDescriptionInterface* offer;
1699 FakeConstraints offer_constraints;
1700 offer_constraints.AddMandatory(
1701 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo, false);
1702 offer_constraints.AddMandatory(
1703 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio, false);
1704 DoCreateOffer(&offer, &offer_constraints);
1705
1706 const cricket::ContentInfo* video_content =
1707 cricket::GetFirstVideoContent(offer->description());
1708 const cricket::VideoContentDescription* video_desc =
1709 static_cast<const cricket::VideoContentDescription*>(
1710 video_content->description);
1711 ASSERT_EQ(cricket::MD_INACTIVE, video_desc->direction());
1712
1713 const cricket::ContentInfo* audio_content =
1714 cricket::GetFirstAudioContent(offer->description());
1715 const cricket::AudioContentDescription* audio_desc =
1716 static_cast<const cricket::AudioContentDescription*>(
1717 audio_content->description);
1718 ASSERT_EQ(cricket::MD_INACTIVE, audio_desc->direction());
1719}
1720
deadbeef653b8e02015-11-11 12:55:10 -08001721// Test that we can use SetConfiguration to change the ICE servers of the
1722// PortAllocator.
1723TEST_F(PeerConnectionInterfaceTest, SetConfigurationChangesIceServers) {
1724 CreatePeerConnection();
1725
1726 PeerConnectionInterface::RTCConfiguration config;
1727 PeerConnectionInterface::IceServer server;
1728 server.uri = "stun:test_hostname";
1729 config.servers.push_back(server);
1730 EXPECT_TRUE(pc_->SetConfiguration(config));
1731
1732 cricket::FakePortAllocator* allocator =
1733 port_allocator_factory_->last_created_allocator();
1734 EXPECT_EQ(1u, allocator->stun_servers().size());
1735 EXPECT_EQ("test_hostname", allocator->stun_servers().begin()->hostname());
1736}
1737
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001738// Test that PeerConnection::Close changes the states to closed and all remote
1739// tracks change state to ended.
1740TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) {
1741 // Initialize a PeerConnection and negotiate local and remote session
1742 // description.
1743 InitiateCall();
1744 ASSERT_EQ(1u, pc_->local_streams()->count());
1745 ASSERT_EQ(1u, pc_->remote_streams()->count());
1746
1747 pc_->Close();
1748
1749 EXPECT_EQ(PeerConnectionInterface::kClosed, pc_->signaling_state());
1750 EXPECT_EQ(PeerConnectionInterface::kIceConnectionClosed,
1751 pc_->ice_connection_state());
1752 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
1753 pc_->ice_gathering_state());
1754
1755 EXPECT_EQ(1u, pc_->local_streams()->count());
1756 EXPECT_EQ(1u, pc_->remote_streams()->count());
1757
1758 scoped_refptr<MediaStreamInterface> remote_stream =
1759 pc_->remote_streams()->at(0);
1760 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1761 remote_stream->GetVideoTracks()[0]->state());
1762 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1763 remote_stream->GetAudioTracks()[0]->state());
1764}
1765
1766// Test that PeerConnection methods fails gracefully after
1767// PeerConnection::Close has been called.
1768TEST_F(PeerConnectionInterfaceTest, CloseAndTestMethods) {
1769 CreatePeerConnection();
1770 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1771 CreateOfferAsRemoteDescription();
1772 CreateAnswerAsLocalDescription();
1773
1774 ASSERT_EQ(1u, pc_->local_streams()->count());
1775 scoped_refptr<MediaStreamInterface> local_stream =
1776 pc_->local_streams()->at(0);
1777
1778 pc_->Close();
1779
1780 pc_->RemoveStream(local_stream);
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001781 EXPECT_FALSE(pc_->AddStream(local_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782
1783 ASSERT_FALSE(local_stream->GetAudioTracks().empty());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001784 rtc::scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 pc_->CreateDtmfSender(local_stream->GetAudioTracks()[0]));
wu@webrtc.org66037362013-08-13 00:09:35 +00001786 EXPECT_TRUE(NULL == dtmf_sender); // local stream has been removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001787
1788 EXPECT_TRUE(pc_->CreateDataChannel("test", NULL) == NULL);
1789
1790 EXPECT_TRUE(pc_->local_description() != NULL);
1791 EXPECT_TRUE(pc_->remote_description() != NULL);
1792
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001793 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -07001794 EXPECT_TRUE(DoCreateOffer(offer.use(), nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001795 rtc::scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -07001796 EXPECT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001797
1798 std::string sdp;
1799 ASSERT_TRUE(pc_->remote_description()->ToString(&sdp));
1800 SessionDescriptionInterface* remote_offer =
1801 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1802 sdp, NULL);
1803 EXPECT_FALSE(DoSetRemoteDescription(remote_offer));
1804
1805 ASSERT_TRUE(pc_->local_description()->ToString(&sdp));
1806 SessionDescriptionInterface* local_offer =
1807 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1808 sdp, NULL);
1809 EXPECT_FALSE(DoSetLocalDescription(local_offer));
1810}
1811
1812// Test that GetStats can still be called after PeerConnection::Close.
1813TEST_F(PeerConnectionInterfaceTest, CloseAndGetStats) {
1814 InitiateCall();
1815 pc_->Close();
1816 DoGetStats(NULL);
1817}
deadbeefab9b2d12015-10-14 11:33:11 -07001818
1819// NOTE: The series of tests below come from what used to be
1820// mediastreamsignaling_unittest.cc, and are mostly aimed at testing that
1821// setting a remote or local description has the expected effects.
1822
1823// This test verifies that the remote MediaStreams corresponding to a received
1824// SDP string is created. In this test the two separate MediaStreams are
1825// signaled.
1826TEST_F(PeerConnectionInterfaceTest, UpdateRemoteStreams) {
1827 FakeConstraints constraints;
1828 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1829 true);
1830 CreatePeerConnection(&constraints);
1831 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1832
1833 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
1834 EXPECT_TRUE(
1835 CompareStreamCollections(observer_.remote_streams(), reference.get()));
1836 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1837 EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != nullptr);
1838
1839 // Create a session description based on another SDP with another
1840 // MediaStream.
1841 CreateAndSetRemoteOffer(kSdpStringWithStream1And2);
1842
1843 rtc::scoped_refptr<StreamCollection> reference2(CreateStreamCollection(2));
1844 EXPECT_TRUE(
1845 CompareStreamCollections(observer_.remote_streams(), reference2.get()));
1846}
1847
1848// This test verifies that when remote tracks are added/removed from SDP, the
1849// created remote streams are updated appropriately.
1850TEST_F(PeerConnectionInterfaceTest,
1851 AddRemoveTrackFromExistingRemoteMediaStream) {
1852 FakeConstraints constraints;
1853 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1854 true);
1855 CreatePeerConnection(&constraints);
1856 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1;
1857 CreateSessionDescriptionAndReference(1, 1, desc_ms1.accept());
1858 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1.release()));
1859 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1860 reference_collection_));
1861
1862 // Add extra audio and video tracks to the same MediaStream.
1863 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks;
1864 CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.accept());
1865 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1_two_tracks.release()));
1866 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1867 reference_collection_));
1868
1869 // Remove the extra audio and video tracks.
1870 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2;
1871 CreateSessionDescriptionAndReference(1, 1, desc_ms2.accept());
1872 EXPECT_TRUE(DoSetRemoteDescription(desc_ms2.release()));
1873 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1874 reference_collection_));
1875}
1876
1877// This tests that remote tracks are ended if a local session description is set
1878// that rejects the media content type.
1879TEST_F(PeerConnectionInterfaceTest, RejectMediaContent) {
1880 FakeConstraints constraints;
1881 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1882 true);
1883 CreatePeerConnection(&constraints);
1884 // First create and set a remote offer, then reject its video content in our
1885 // answer.
1886 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1887 ASSERT_EQ(1u, observer_.remote_streams()->count());
1888 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1889 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1890 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1891
1892 rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video =
1893 remote_stream->GetVideoTracks()[0];
1894 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state());
1895 rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio =
1896 remote_stream->GetAudioTracks()[0];
1897 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1898
1899 rtc::scoped_ptr<SessionDescriptionInterface> local_answer;
deadbeefc80741f2015-10-22 13:14:45 -07001900 EXPECT_TRUE(DoCreateAnswer(local_answer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001901 cricket::ContentInfo* video_info =
1902 local_answer->description()->GetContentByName("video");
1903 video_info->rejected = true;
1904 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1905 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1906 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1907
1908 // Now create an offer where we reject both video and audio.
1909 rtc::scoped_ptr<SessionDescriptionInterface> local_offer;
deadbeefc80741f2015-10-22 13:14:45 -07001910 EXPECT_TRUE(DoCreateOffer(local_offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001911 video_info = local_offer->description()->GetContentByName("video");
1912 ASSERT_TRUE(video_info != nullptr);
1913 video_info->rejected = true;
1914 cricket::ContentInfo* audio_info =
1915 local_offer->description()->GetContentByName("audio");
1916 ASSERT_TRUE(audio_info != nullptr);
1917 audio_info->rejected = true;
1918 EXPECT_TRUE(DoSetLocalDescription(local_offer.release()));
1919 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1920 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state());
1921}
1922
1923// This tests that we won't crash if the remote track has been removed outside
1924// of PeerConnection and then PeerConnection tries to reject the track.
1925TEST_F(PeerConnectionInterfaceTest, RemoveTrackThenRejectMediaContent) {
1926 FakeConstraints constraints;
1927 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1928 true);
1929 CreatePeerConnection(&constraints);
1930 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1931 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1932 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
1933 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
1934
1935 rtc::scoped_ptr<SessionDescriptionInterface> local_answer(
1936 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
1937 kSdpStringWithStream1, nullptr));
1938 cricket::ContentInfo* video_info =
1939 local_answer->description()->GetContentByName("video");
1940 video_info->rejected = true;
1941 cricket::ContentInfo* audio_info =
1942 local_answer->description()->GetContentByName("audio");
1943 audio_info->rejected = true;
1944 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1945
1946 // No crash is a pass.
1947}
1948
deadbeef5e97fb52015-10-15 12:49:08 -07001949// This tests that if a recvonly remote description is set, no remote streams
1950// will be created, even if the description contains SSRCs/MSIDs.
1951// See: https://code.google.com/p/webrtc/issues/detail?id=5054
1952TEST_F(PeerConnectionInterfaceTest, RecvonlyDescriptionDoesntCreateStream) {
1953 FakeConstraints constraints;
1954 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1955 true);
1956 CreatePeerConnection(&constraints);
1957
1958 std::string recvonly_offer = kSdpStringWithStream1;
1959 rtc::replace_substrs(kSendrecv, strlen(kSendrecv), kRecvonly,
1960 strlen(kRecvonly), &recvonly_offer);
1961 CreateAndSetRemoteOffer(recvonly_offer);
1962
1963 EXPECT_EQ(0u, observer_.remote_streams()->count());
1964}
1965
deadbeefab9b2d12015-10-14 11:33:11 -07001966// This tests that a default MediaStream is created if a remote session
1967// description doesn't contain any streams and no MSID support.
1968// It also tests that the default stream is updated if a video m-line is added
1969// in a subsequent session description.
1970TEST_F(PeerConnectionInterfaceTest, SdpWithoutMsidCreatesDefaultStream) {
1971 FakeConstraints constraints;
1972 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1973 true);
1974 CreatePeerConnection(&constraints);
1975 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
1976
1977 ASSERT_EQ(1u, observer_.remote_streams()->count());
1978 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1979
1980 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
1981 EXPECT_EQ(0u, remote_stream->GetVideoTracks().size());
1982 EXPECT_EQ("default", remote_stream->label());
1983
1984 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
1985 ASSERT_EQ(1u, observer_.remote_streams()->count());
1986 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1987 EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
1988 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1989 EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
1990}
1991
1992// This tests that a default MediaStream is created if a remote session
1993// description doesn't contain any streams and media direction is send only.
1994TEST_F(PeerConnectionInterfaceTest,
1995 SendOnlySdpWithoutMsidCreatesDefaultStream) {
1996 FakeConstraints constraints;
1997 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1998 true);
1999 CreatePeerConnection(&constraints);
2000 CreateAndSetRemoteOffer(kSdpStringSendOnlyWithoutStreams);
2001
2002 ASSERT_EQ(1u, observer_.remote_streams()->count());
2003 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2004
2005 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
2006 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
2007 EXPECT_EQ("default", remote_stream->label());
2008}
2009
2010// This tests that it won't crash when PeerConnection tries to remove
2011// a remote track that as already been removed from the MediaStream.
2012TEST_F(PeerConnectionInterfaceTest, RemoveAlreadyGoneRemoteStream) {
2013 FakeConstraints constraints;
2014 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2015 true);
2016 CreatePeerConnection(&constraints);
2017 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2018 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2019 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
2020 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
2021
2022 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2023
2024 // No crash is a pass.
2025}
2026
2027// This tests that a default MediaStream is created if the remote session
2028// description doesn't contain any streams and don't contain an indication if
2029// MSID is supported.
2030TEST_F(PeerConnectionInterfaceTest,
2031 SdpWithoutMsidAndStreamsCreatesDefaultStream) {
2032 FakeConstraints constraints;
2033 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2034 true);
2035 CreatePeerConnection(&constraints);
2036 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2037
2038 ASSERT_EQ(1u, observer_.remote_streams()->count());
2039 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2040 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
2041 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
2042}
2043
2044// This tests that a default MediaStream is not created if the remote session
2045// description doesn't contain any streams but does support MSID.
2046TEST_F(PeerConnectionInterfaceTest, SdpWithMsidDontCreatesDefaultStream) {
2047 FakeConstraints constraints;
2048 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2049 true);
2050 CreatePeerConnection(&constraints);
2051 CreateAndSetRemoteOffer(kSdpStringWithMsidWithoutStreams);
2052 EXPECT_EQ(0u, observer_.remote_streams()->count());
2053}
2054
deadbeefbda7e0b2015-12-08 17:13:40 -08002055// This tests that when setting a new description, the old default tracks are
2056// not destroyed and recreated.
2057// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5250
2058TEST_F(PeerConnectionInterfaceTest, DefaultTracksNotDestroyedAndRecreated) {
2059 FakeConstraints constraints;
2060 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2061 true);
2062 CreatePeerConnection(&constraints);
2063 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2064
2065 ASSERT_EQ(1u, observer_.remote_streams()->count());
2066 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2067 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2068
2069 // Set the track to "disabled", then set a new description and ensure the
2070 // track is still disabled, which ensures it hasn't been recreated.
2071 remote_stream->GetAudioTracks()[0]->set_enabled(false);
2072 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2073 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2074 EXPECT_FALSE(remote_stream->GetAudioTracks()[0]->enabled());
2075}
2076
deadbeefab9b2d12015-10-14 11:33:11 -07002077// This tests that a default MediaStream is not created if a remote session
2078// description is updated to not have any MediaStreams.
2079TEST_F(PeerConnectionInterfaceTest, VerifyDefaultStreamIsNotCreated) {
2080 FakeConstraints constraints;
2081 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2082 true);
2083 CreatePeerConnection(&constraints);
2084 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2085 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
2086 EXPECT_TRUE(
2087 CompareStreamCollections(observer_.remote_streams(), reference.get()));
2088
2089 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2090 EXPECT_EQ(0u, observer_.remote_streams()->count());
2091}
2092
2093// This tests that an RtpSender is created when the local description is set
2094// after adding a local stream.
2095// TODO(deadbeef): This test and the one below it need to be updated when
2096// an RtpSender's lifetime isn't determined by when a local description is set.
2097TEST_F(PeerConnectionInterfaceTest, LocalDescriptionChanged) {
2098 FakeConstraints constraints;
2099 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2100 true);
2101 CreatePeerConnection(&constraints);
2102 // Create an offer just to ensure we have an identity before we manually
2103 // call SetLocalDescription.
2104 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002105 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002106
2107 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2108 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2109
2110 pc_->AddStream(reference_collection_->at(0));
2111 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2112 auto senders = pc_->GetSenders();
2113 EXPECT_EQ(4u, senders.size());
2114 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2115 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2116 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2117 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2118
2119 // Remove an audio and video track.
deadbeeffac06552015-11-25 11:26:01 -08002120 pc_->RemoveStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002121 rtc::scoped_ptr<SessionDescriptionInterface> desc_2;
2122 CreateSessionDescriptionAndReference(1, 1, desc_2.accept());
deadbeeffac06552015-11-25 11:26:01 -08002123 pc_->AddStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002124 EXPECT_TRUE(DoSetLocalDescription(desc_2.release()));
2125 senders = pc_->GetSenders();
2126 EXPECT_EQ(2u, senders.size());
2127 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2128 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2129 EXPECT_FALSE(ContainsSender(senders, kAudioTracks[1]));
2130 EXPECT_FALSE(ContainsSender(senders, kVideoTracks[1]));
2131}
2132
2133// This tests that an RtpSender is created when the local description is set
2134// before adding a local stream.
2135TEST_F(PeerConnectionInterfaceTest,
2136 AddLocalStreamAfterLocalDescriptionChanged) {
2137 FakeConstraints constraints;
2138 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2139 true);
2140 CreatePeerConnection(&constraints);
2141 // Create an offer just to ensure we have an identity before we manually
2142 // call SetLocalDescription.
2143 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002144 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002145
2146 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2147 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2148
2149 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2150 auto senders = pc_->GetSenders();
2151 EXPECT_EQ(0u, senders.size());
2152
2153 pc_->AddStream(reference_collection_->at(0));
2154 senders = pc_->GetSenders();
2155 EXPECT_EQ(4u, senders.size());
2156 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2157 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2158 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2159 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2160}
2161
2162// This tests that the expected behavior occurs if the SSRC on a local track is
2163// changed when SetLocalDescription is called.
2164TEST_F(PeerConnectionInterfaceTest,
2165 ChangeSsrcOnTrackInLocalSessionDescription) {
2166 FakeConstraints constraints;
2167 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2168 true);
2169 CreatePeerConnection(&constraints);
2170 // Create an offer just to ensure we have an identity before we manually
2171 // call SetLocalDescription.
2172 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002173 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002174
2175 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2176 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2177 std::string sdp;
2178 desc->ToString(&sdp);
2179
2180 pc_->AddStream(reference_collection_->at(0));
2181 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2182 auto senders = pc_->GetSenders();
2183 EXPECT_EQ(2u, senders.size());
2184 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2185 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2186
2187 // Change the ssrc of the audio and video track.
2188 std::string ssrc_org = "a=ssrc:1";
2189 std::string ssrc_to = "a=ssrc:97";
2190 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2191 ssrc_to.length(), &sdp);
2192 ssrc_org = "a=ssrc:2";
2193 ssrc_to = "a=ssrc:98";
2194 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2195 ssrc_to.length(), &sdp);
2196 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2197 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2198 nullptr));
2199
2200 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2201 senders = pc_->GetSenders();
2202 EXPECT_EQ(2u, senders.size());
2203 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2204 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2205 // TODO(deadbeef): Once RtpSenders expose parameters, check that the SSRC
2206 // changed.
2207}
2208
2209// This tests that the expected behavior occurs if a new session description is
2210// set with the same tracks, but on a different MediaStream.
2211TEST_F(PeerConnectionInterfaceTest, SignalSameTracksInSeparateMediaStream) {
2212 FakeConstraints constraints;
2213 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2214 true);
2215 CreatePeerConnection(&constraints);
2216 // Create an offer just to ensure we have an identity before we manually
2217 // call SetLocalDescription.
2218 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002219 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002220
2221 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2222 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2223 std::string sdp;
2224 desc->ToString(&sdp);
2225
2226 pc_->AddStream(reference_collection_->at(0));
2227 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2228 auto senders = pc_->GetSenders();
2229 EXPECT_EQ(2u, senders.size());
2230 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2231 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2232
2233 // Add a new MediaStream but with the same tracks as in the first stream.
2234 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
2235 webrtc::MediaStream::Create(kStreams[1]));
2236 stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]);
2237 stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]);
2238 pc_->AddStream(stream_1);
2239
2240 // Replace msid in the original SDP.
2241 rtc::replace_substrs(kStreams[0], strlen(kStreams[0]), kStreams[1],
2242 strlen(kStreams[1]), &sdp);
2243
2244 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2245 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2246 nullptr));
2247
2248 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2249 senders = pc_->GetSenders();
2250 EXPECT_EQ(2u, senders.size());
2251 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2252 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2253}
2254
2255// The following tests verify that session options are created correctly.
deadbeefc80741f2015-10-22 13:14:45 -07002256// TODO(deadbeef): Convert these tests to be more end-to-end. Instead of
2257// "verify options are converted correctly", should be "pass options into
2258// CreateOffer and verify the correct offer is produced."
deadbeefab9b2d12015-10-14 11:33:11 -07002259
2260TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidAudioOption) {
2261 RTCOfferAnswerOptions rtc_options;
2262 rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
2263
2264 cricket::MediaSessionOptions options;
2265 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2266
2267 rtc_options.offer_to_receive_audio =
2268 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2269 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2270}
2271
2272TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidVideoOption) {
2273 RTCOfferAnswerOptions rtc_options;
2274 rtc_options.offer_to_receive_video = RTCOfferAnswerOptions::kUndefined - 1;
2275
2276 cricket::MediaSessionOptions options;
2277 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2278
2279 rtc_options.offer_to_receive_video =
2280 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2281 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2282}
2283
2284// Test that a MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002285// OfferToReceiveAudio and OfferToReceiveVideo options are set.
deadbeefab9b2d12015-10-14 11:33:11 -07002286TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
2287 RTCOfferAnswerOptions rtc_options;
2288 rtc_options.offer_to_receive_audio = 1;
2289 rtc_options.offer_to_receive_video = 1;
2290
2291 cricket::MediaSessionOptions options;
2292 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2293 EXPECT_TRUE(options.has_audio());
2294 EXPECT_TRUE(options.has_video());
2295 EXPECT_TRUE(options.bundle_enabled);
2296}
2297
2298// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002299// OfferToReceiveAudio is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002300TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudio) {
2301 RTCOfferAnswerOptions rtc_options;
2302 rtc_options.offer_to_receive_audio = 1;
2303
2304 cricket::MediaSessionOptions options;
2305 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2306 EXPECT_TRUE(options.has_audio());
2307 EXPECT_FALSE(options.has_video());
2308 EXPECT_TRUE(options.bundle_enabled);
2309}
2310
2311// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002312// the default OfferOptions are used.
deadbeefab9b2d12015-10-14 11:33:11 -07002313TEST(CreateSessionOptionsTest, GetDefaultMediaSessionOptionsForOffer) {
2314 RTCOfferAnswerOptions rtc_options;
2315
2316 cricket::MediaSessionOptions options;
2317 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
deadbeefc80741f2015-10-22 13:14:45 -07002318 EXPECT_TRUE(options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002319 EXPECT_FALSE(options.has_video());
deadbeefc80741f2015-10-22 13:14:45 -07002320 EXPECT_TRUE(options.bundle_enabled);
deadbeefab9b2d12015-10-14 11:33:11 -07002321 EXPECT_TRUE(options.vad_enabled);
2322 EXPECT_FALSE(options.transport_options.ice_restart);
2323}
2324
2325// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002326// OfferToReceiveVideo is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002327TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithVideo) {
2328 RTCOfferAnswerOptions rtc_options;
2329 rtc_options.offer_to_receive_audio = 0;
2330 rtc_options.offer_to_receive_video = 1;
2331
2332 cricket::MediaSessionOptions options;
2333 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2334 EXPECT_FALSE(options.has_audio());
2335 EXPECT_TRUE(options.has_video());
2336 EXPECT_TRUE(options.bundle_enabled);
2337}
2338
2339// Test that a correct MediaSessionOptions is created for an offer if
2340// UseRtpMux is set to false.
2341TEST(CreateSessionOptionsTest,
2342 GetMediaSessionOptionsForOfferWithBundleDisabled) {
2343 RTCOfferAnswerOptions rtc_options;
2344 rtc_options.offer_to_receive_audio = 1;
2345 rtc_options.offer_to_receive_video = 1;
2346 rtc_options.use_rtp_mux = false;
2347
2348 cricket::MediaSessionOptions options;
2349 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2350 EXPECT_TRUE(options.has_audio());
2351 EXPECT_TRUE(options.has_video());
2352 EXPECT_FALSE(options.bundle_enabled);
2353}
2354
2355// Test that a correct MediaSessionOptions is created to restart ice if
2356// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
2357// have |transport_options.ice_restart| set.
2358TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithIceRestart) {
2359 RTCOfferAnswerOptions rtc_options;
2360 rtc_options.ice_restart = true;
2361
2362 cricket::MediaSessionOptions options;
2363 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2364 EXPECT_TRUE(options.transport_options.ice_restart);
2365
2366 rtc_options = RTCOfferAnswerOptions();
2367 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2368 EXPECT_FALSE(options.transport_options.ice_restart);
2369}
2370
2371// Test that the MediaConstraints in an answer don't affect if audio and video
2372// is offered in an offer but that if kOfferToReceiveAudio or
2373// kOfferToReceiveVideo constraints are true in an offer, the media type will be
2374// included in subsequent answers.
2375TEST(CreateSessionOptionsTest, MediaConstraintsInAnswer) {
2376 FakeConstraints answer_c;
2377 answer_c.SetMandatoryReceiveAudio(true);
2378 answer_c.SetMandatoryReceiveVideo(true);
2379
2380 cricket::MediaSessionOptions answer_options;
2381 EXPECT_TRUE(ParseConstraintsForAnswer(&answer_c, &answer_options));
2382 EXPECT_TRUE(answer_options.has_audio());
2383 EXPECT_TRUE(answer_options.has_video());
2384
deadbeefc80741f2015-10-22 13:14:45 -07002385 RTCOfferAnswerOptions rtc_offer_options;
deadbeefab9b2d12015-10-14 11:33:11 -07002386
2387 cricket::MediaSessionOptions offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002388 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_offer_options, &offer_options));
2389 EXPECT_TRUE(offer_options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002390 EXPECT_FALSE(offer_options.has_video());
2391
deadbeefc80741f2015-10-22 13:14:45 -07002392 RTCOfferAnswerOptions updated_rtc_offer_options;
2393 updated_rtc_offer_options.offer_to_receive_audio = 1;
2394 updated_rtc_offer_options.offer_to_receive_video = 1;
deadbeefab9b2d12015-10-14 11:33:11 -07002395
2396 cricket::MediaSessionOptions updated_offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002397 EXPECT_TRUE(ConvertRtcOptionsForOffer(updated_rtc_offer_options,
deadbeefab9b2d12015-10-14 11:33:11 -07002398 &updated_offer_options));
2399 EXPECT_TRUE(updated_offer_options.has_audio());
2400 EXPECT_TRUE(updated_offer_options.has_video());
2401
2402 // Since an offer has been created with both audio and video, subsequent
2403 // offers and answers should contain both audio and video.
2404 // Answers will only contain the media types that exist in the offer
2405 // regardless of the value of |updated_answer_options.has_audio| and
2406 // |updated_answer_options.has_video|.
2407 FakeConstraints updated_answer_c;
2408 answer_c.SetMandatoryReceiveAudio(false);
2409 answer_c.SetMandatoryReceiveVideo(false);
2410
2411 cricket::MediaSessionOptions updated_answer_options;
2412 EXPECT_TRUE(
2413 ParseConstraintsForAnswer(&updated_answer_c, &updated_answer_options));
2414 EXPECT_TRUE(updated_answer_options.has_audio());
2415 EXPECT_TRUE(updated_answer_options.has_video());
deadbeefab9b2d12015-10-14 11:33:11 -07002416}