blob: 930f538ebdfda264da623bd1cc03e0182d6a16e8 [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
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001201// Test that we can specify a certain track that we want statistics about.
1202TEST_F(PeerConnectionInterfaceTest, GetStatsForSpecificTrack) {
1203 InitiateCall();
1204 ASSERT_LT(0u, pc_->remote_streams()->count());
1205 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetAudioTracks().size());
1206 scoped_refptr<MediaStreamTrackInterface> remote_audio =
1207 pc_->remote_streams()->at(0)->GetAudioTracks()[0];
1208 EXPECT_TRUE(DoGetStats(remote_audio));
1209
1210 // Remove the stream. Since we are sending to our selves the local
1211 // and the remote stream is the same.
1212 pc_->RemoveStream(pc_->local_streams()->at(0));
1213 // Do a re-negotiation.
1214 CreateOfferReceiveAnswer();
1215
1216 ASSERT_EQ(0u, pc_->remote_streams()->count());
1217
1218 // Test that we still can get statistics for the old track. Even if it is not
1219 // sent any longer.
1220 EXPECT_TRUE(DoGetStats(remote_audio));
1221}
1222
1223// Test that we can get stats on a video track.
1224TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
1225 InitiateCall();
1226 ASSERT_LT(0u, pc_->remote_streams()->count());
1227 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetVideoTracks().size());
1228 scoped_refptr<MediaStreamTrackInterface> remote_video =
1229 pc_->remote_streams()->at(0)->GetVideoTracks()[0];
1230 EXPECT_TRUE(DoGetStats(remote_video));
1231}
1232
1233// Test that we don't get statistics for an invalid track.
tommi@webrtc.org908f57e2014-07-21 11:44:39 +00001234// TODO(tommi): Fix this test. DoGetStats will return true
1235// for the unknown track (since GetStats is async), but no
1236// data is returned for the track.
1237TEST_F(PeerConnectionInterfaceTest, DISABLED_GetStatsForInvalidTrack) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 InitiateCall();
1239 scoped_refptr<AudioTrackInterface> unknown_audio_track(
1240 pc_factory_->CreateAudioTrack("unknown track", NULL));
1241 EXPECT_FALSE(DoGetStats(unknown_audio_track));
1242}
1243
1244// This test setup two RTP data channels in loop back.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245TEST_F(PeerConnectionInterfaceTest, TestDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001246 FakeConstraints constraints;
1247 constraints.SetAllowRtpDataChannels();
1248 CreatePeerConnection(&constraints);
1249 scoped_refptr<DataChannelInterface> data1 =
1250 pc_->CreateDataChannel("test1", NULL);
1251 scoped_refptr<DataChannelInterface> data2 =
1252 pc_->CreateDataChannel("test2", NULL);
1253 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001254 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001255 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001256 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257 new MockDataChannelObserver(data2));
1258
1259 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1260 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1261 std::string data_to_send1 = "testing testing";
1262 std::string data_to_send2 = "testing something else";
1263 EXPECT_FALSE(data1->Send(DataBuffer(data_to_send1)));
1264
1265 CreateOfferReceiveAnswer();
1266 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1267 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1268
1269 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1270 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1271 EXPECT_TRUE(data1->Send(DataBuffer(data_to_send1)));
1272 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1273
1274 EXPECT_EQ_WAIT(data_to_send1, observer1->last_message(), kTimeout);
1275 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1276
1277 data1->Close();
1278 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1279 CreateOfferReceiveAnswer();
1280 EXPECT_FALSE(observer1->IsOpen());
1281 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1282 EXPECT_TRUE(observer2->IsOpen());
1283
1284 data_to_send2 = "testing something else again";
1285 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1286
1287 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1288}
1289
1290// This test verifies that sendnig binary data over RTP data channels should
1291// fail.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292TEST_F(PeerConnectionInterfaceTest, TestSendBinaryOnRtpDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293 FakeConstraints constraints;
1294 constraints.SetAllowRtpDataChannels();
1295 CreatePeerConnection(&constraints);
1296 scoped_refptr<DataChannelInterface> data1 =
1297 pc_->CreateDataChannel("test1", NULL);
1298 scoped_refptr<DataChannelInterface> data2 =
1299 pc_->CreateDataChannel("test2", NULL);
1300 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001301 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001302 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001303 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 new MockDataChannelObserver(data2));
1305
1306 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1307 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1308
1309 CreateOfferReceiveAnswer();
1310 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1311 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1312
1313 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1314 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1315
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001316 rtc::Buffer buffer("test", 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317 EXPECT_FALSE(data1->Send(DataBuffer(buffer, true)));
1318}
1319
1320// This test setup a RTP data channels in loop back and test that a channel is
1321// opened even if the remote end answer with a zero SSRC.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322TEST_F(PeerConnectionInterfaceTest, TestSendOnlyDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001323 FakeConstraints constraints;
1324 constraints.SetAllowRtpDataChannels();
1325 CreatePeerConnection(&constraints);
1326 scoped_refptr<DataChannelInterface> data1 =
1327 pc_->CreateDataChannel("test1", NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001328 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 new MockDataChannelObserver(data1));
1330
1331 CreateOfferReceiveAnswerWithoutSsrc();
1332
1333 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1334
1335 data1->Close();
1336 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1337 CreateOfferReceiveAnswerWithoutSsrc();
1338 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1339 EXPECT_FALSE(observer1->IsOpen());
1340}
1341
1342// This test that if a data channel is added in an answer a receive only channel
1343// channel is created.
1344TEST_F(PeerConnectionInterfaceTest, TestReceiveOnlyDataChannel) {
1345 FakeConstraints constraints;
1346 constraints.SetAllowRtpDataChannels();
1347 CreatePeerConnection(&constraints);
1348
1349 std::string offer_label = "offer_channel";
1350 scoped_refptr<DataChannelInterface> offer_channel =
1351 pc_->CreateDataChannel(offer_label, NULL);
1352
1353 CreateOfferAsLocalDescription();
1354
1355 // Replace the data channel label in the offer and apply it as an answer.
1356 std::string receive_label = "answer_channel";
1357 std::string sdp;
1358 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001359 rtc::replace_substrs(offer_label.c_str(), offer_label.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 receive_label.c_str(), receive_label.length(),
1361 &sdp);
1362 CreateAnswerAsRemoteDescription(sdp);
1363
1364 // Verify that a new incoming data channel has been created and that
1365 // it is open but can't we written to.
1366 ASSERT_TRUE(observer_.last_datachannel_ != NULL);
1367 DataChannelInterface* received_channel = observer_.last_datachannel_;
1368 EXPECT_EQ(DataChannelInterface::kConnecting, received_channel->state());
1369 EXPECT_EQ(receive_label, received_channel->label());
1370 EXPECT_FALSE(received_channel->Send(DataBuffer("something")));
1371
1372 // Verify that the channel we initially offered has been rejected.
1373 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1374
1375 // Do another offer / answer exchange and verify that the data channel is
1376 // opened.
1377 CreateOfferReceiveAnswer();
1378 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, received_channel->state(),
1379 kTimeout);
1380}
1381
1382// This test that no data channel is returned if a reliable channel is
1383// requested.
1384// TODO(perkj): Remove this test once reliable channels are implemented.
1385TEST_F(PeerConnectionInterfaceTest, CreateReliableRtpDataChannelShouldFail) {
1386 FakeConstraints constraints;
1387 constraints.SetAllowRtpDataChannels();
1388 CreatePeerConnection(&constraints);
1389
1390 std::string label = "test";
1391 webrtc::DataChannelInit config;
1392 config.reliable = true;
1393 scoped_refptr<DataChannelInterface> channel =
1394 pc_->CreateDataChannel(label, &config);
1395 EXPECT_TRUE(channel == NULL);
1396}
1397
deadbeefab9b2d12015-10-14 11:33:11 -07001398// Verifies that duplicated label is not allowed for RTP data channel.
1399TEST_F(PeerConnectionInterfaceTest, RtpDuplicatedLabelNotAllowed) {
1400 FakeConstraints constraints;
1401 constraints.SetAllowRtpDataChannels();
1402 CreatePeerConnection(&constraints);
1403
1404 std::string label = "test";
1405 scoped_refptr<DataChannelInterface> channel =
1406 pc_->CreateDataChannel(label, nullptr);
1407 EXPECT_NE(channel, nullptr);
1408
1409 scoped_refptr<DataChannelInterface> dup_channel =
1410 pc_->CreateDataChannel(label, nullptr);
1411 EXPECT_EQ(dup_channel, nullptr);
1412}
1413
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414// This tests that a SCTP data channel is returned using different
1415// DataChannelInit configurations.
1416TEST_F(PeerConnectionInterfaceTest, CreateSctpDataChannel) {
1417 FakeConstraints constraints;
1418 constraints.SetAllowDtlsSctpDataChannels();
1419 CreatePeerConnection(&constraints);
1420
1421 webrtc::DataChannelInit config;
1422
1423 scoped_refptr<DataChannelInterface> channel =
1424 pc_->CreateDataChannel("1", &config);
1425 EXPECT_TRUE(channel != NULL);
1426 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001427 EXPECT_TRUE(observer_.renegotiation_needed_);
1428 observer_.renegotiation_needed_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001429
1430 config.ordered = false;
1431 channel = pc_->CreateDataChannel("2", &config);
1432 EXPECT_TRUE(channel != NULL);
1433 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001434 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001435
1436 config.ordered = true;
1437 config.maxRetransmits = 0;
1438 channel = pc_->CreateDataChannel("3", &config);
1439 EXPECT_TRUE(channel != NULL);
1440 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001441 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001442
1443 config.maxRetransmits = -1;
1444 config.maxRetransmitTime = 0;
1445 channel = pc_->CreateDataChannel("4", &config);
1446 EXPECT_TRUE(channel != NULL);
1447 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001448 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001449}
1450
1451// This tests that no data channel is returned if both maxRetransmits and
1452// maxRetransmitTime are set for SCTP data channels.
1453TEST_F(PeerConnectionInterfaceTest,
1454 CreateSctpDataChannelShouldFailForInvalidConfig) {
1455 FakeConstraints constraints;
1456 constraints.SetAllowDtlsSctpDataChannels();
1457 CreatePeerConnection(&constraints);
1458
1459 std::string label = "test";
1460 webrtc::DataChannelInit config;
1461 config.maxRetransmits = 0;
1462 config.maxRetransmitTime = 0;
1463
1464 scoped_refptr<DataChannelInterface> channel =
1465 pc_->CreateDataChannel(label, &config);
1466 EXPECT_TRUE(channel == NULL);
1467}
1468
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469// The test verifies that creating a SCTP data channel with an id already in use
1470// or out of range should fail.
1471TEST_F(PeerConnectionInterfaceTest,
1472 CreateSctpDataChannelWithInvalidIdShouldFail) {
1473 FakeConstraints constraints;
1474 constraints.SetAllowDtlsSctpDataChannels();
1475 CreatePeerConnection(&constraints);
1476
1477 webrtc::DataChannelInit config;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001478 scoped_refptr<DataChannelInterface> channel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001479
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001480 config.id = 1;
1481 channel = pc_->CreateDataChannel("1", &config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 EXPECT_TRUE(channel != NULL);
1483 EXPECT_EQ(1, channel->id());
1484
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001485 channel = pc_->CreateDataChannel("x", &config);
1486 EXPECT_TRUE(channel == NULL);
1487
1488 config.id = cricket::kMaxSctpSid;
1489 channel = pc_->CreateDataChannel("max", &config);
1490 EXPECT_TRUE(channel != NULL);
1491 EXPECT_EQ(config.id, channel->id());
1492
1493 config.id = cricket::kMaxSctpSid + 1;
1494 channel = pc_->CreateDataChannel("x", &config);
1495 EXPECT_TRUE(channel == NULL);
1496}
1497
deadbeefab9b2d12015-10-14 11:33:11 -07001498// Verifies that duplicated label is allowed for SCTP data channel.
1499TEST_F(PeerConnectionInterfaceTest, SctpDuplicatedLabelAllowed) {
1500 FakeConstraints constraints;
1501 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1502 true);
1503 CreatePeerConnection(&constraints);
1504
1505 std::string label = "test";
1506 scoped_refptr<DataChannelInterface> channel =
1507 pc_->CreateDataChannel(label, nullptr);
1508 EXPECT_NE(channel, nullptr);
1509
1510 scoped_refptr<DataChannelInterface> dup_channel =
1511 pc_->CreateDataChannel(label, nullptr);
1512 EXPECT_NE(dup_channel, nullptr);
1513}
1514
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001515// This test verifies that OnRenegotiationNeeded is fired for every new RTP
1516// DataChannel.
1517TEST_F(PeerConnectionInterfaceTest, RenegotiationNeededForNewRtpDataChannel) {
1518 FakeConstraints constraints;
1519 constraints.SetAllowRtpDataChannels();
1520 CreatePeerConnection(&constraints);
1521
1522 scoped_refptr<DataChannelInterface> dc1 =
1523 pc_->CreateDataChannel("test1", NULL);
1524 EXPECT_TRUE(observer_.renegotiation_needed_);
1525 observer_.renegotiation_needed_ = false;
1526
1527 scoped_refptr<DataChannelInterface> dc2 =
1528 pc_->CreateDataChannel("test2", NULL);
1529 EXPECT_TRUE(observer_.renegotiation_needed_);
1530}
1531
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532// This test that a data channel closes when a PeerConnection is deleted/closed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533TEST_F(PeerConnectionInterfaceTest, DataChannelCloseWhenPeerConnectionClose) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001534 FakeConstraints constraints;
1535 constraints.SetAllowRtpDataChannels();
1536 CreatePeerConnection(&constraints);
1537
1538 scoped_refptr<DataChannelInterface> data1 =
1539 pc_->CreateDataChannel("test1", NULL);
1540 scoped_refptr<DataChannelInterface> data2 =
1541 pc_->CreateDataChannel("test2", NULL);
1542 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001543 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001545 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 new MockDataChannelObserver(data2));
1547
1548 CreateOfferReceiveAnswer();
1549 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1550 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1551
1552 ReleasePeerConnection();
1553 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1554 EXPECT_EQ(DataChannelInterface::kClosed, data2->state());
1555}
1556
1557// This test that data channels can be rejected in an answer.
1558TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
1559 FakeConstraints constraints;
1560 constraints.SetAllowRtpDataChannels();
1561 CreatePeerConnection(&constraints);
1562
1563 scoped_refptr<DataChannelInterface> offer_channel(
1564 pc_->CreateDataChannel("offer_channel", NULL));
1565
1566 CreateOfferAsLocalDescription();
1567
1568 // Create an answer where the m-line for data channels are rejected.
1569 std::string sdp;
1570 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
1571 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
1572 SessionDescriptionInterface::kAnswer);
1573 EXPECT_TRUE(answer->Initialize(sdp, NULL));
1574 cricket::ContentInfo* data_info =
1575 answer->description()->GetContentByName("data");
1576 data_info->rejected = true;
1577
1578 DoSetRemoteDescription(answer);
1579 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1580}
1581
1582// Test that we can create a session description from an SDP string from
1583// FireFox, use it as a remote session description, generate an answer and use
1584// the answer as a local description.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001585TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001586 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001587 FakeConstraints constraints;
1588 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1589 true);
1590 CreatePeerConnection(&constraints);
1591 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1592 SessionDescriptionInterface* desc =
1593 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001594 webrtc::kFireFoxSdpOffer, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595 EXPECT_TRUE(DoSetSessionDescription(desc, false));
1596 CreateAnswerAsLocalDescription();
1597 ASSERT_TRUE(pc_->local_description() != NULL);
1598 ASSERT_TRUE(pc_->remote_description() != NULL);
1599
1600 const cricket::ContentInfo* content =
1601 cricket::GetFirstAudioContent(pc_->local_description()->description());
1602 ASSERT_TRUE(content != NULL);
1603 EXPECT_FALSE(content->rejected);
1604
1605 content =
1606 cricket::GetFirstVideoContent(pc_->local_description()->description());
1607 ASSERT_TRUE(content != NULL);
1608 EXPECT_FALSE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001609#ifdef HAVE_SCTP
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 content =
1611 cricket::GetFirstDataContent(pc_->local_description()->description());
1612 ASSERT_TRUE(content != NULL);
1613 EXPECT_TRUE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001614#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615}
1616
1617// Test that we can create an audio only offer and receive an answer with a
1618// limited set of audio codecs and receive an updated offer with more audio
1619// codecs, where the added codecs are not supported.
1620TEST_F(PeerConnectionInterfaceTest, ReceiveUpdatedAudioOfferWithBadCodecs) {
1621 CreatePeerConnection();
1622 AddVoiceStream("audio_label");
1623 CreateOfferAsLocalDescription();
1624
1625 SessionDescriptionInterface* answer =
1626 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
jbauchfabe2c92015-07-16 13:43:14 -07001627 webrtc::kAudioSdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628 EXPECT_TRUE(DoSetSessionDescription(answer, false));
1629
1630 SessionDescriptionInterface* updated_offer =
1631 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001632 webrtc::kAudioSdpWithUnsupportedCodecs,
1633 nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634 EXPECT_TRUE(DoSetSessionDescription(updated_offer, false));
1635 CreateAnswerAsLocalDescription();
1636}
1637
deadbeefc80741f2015-10-22 13:14:45 -07001638// Test that if we're receiving (but not sending) a track, subsequent offers
1639// will have m-lines with a=recvonly.
1640TEST_F(PeerConnectionInterfaceTest, CreateSubsequentRecvOnlyOffer) {
1641 FakeConstraints constraints;
1642 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1643 true);
1644 CreatePeerConnection(&constraints);
1645 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1646 CreateAnswerAsLocalDescription();
1647
1648 // At this point we should be receiving stream 1, but not sending anything.
1649 // A new offer should be recvonly.
1650 SessionDescriptionInterface* offer;
1651 DoCreateOffer(&offer, nullptr);
1652
1653 const cricket::ContentInfo* video_content =
1654 cricket::GetFirstVideoContent(offer->description());
1655 const cricket::VideoContentDescription* video_desc =
1656 static_cast<const cricket::VideoContentDescription*>(
1657 video_content->description);
1658 ASSERT_EQ(cricket::MD_RECVONLY, video_desc->direction());
1659
1660 const cricket::ContentInfo* audio_content =
1661 cricket::GetFirstAudioContent(offer->description());
1662 const cricket::AudioContentDescription* audio_desc =
1663 static_cast<const cricket::AudioContentDescription*>(
1664 audio_content->description);
1665 ASSERT_EQ(cricket::MD_RECVONLY, audio_desc->direction());
1666}
1667
1668// Test that if we're receiving (but not sending) a track, and the
1669// offerToReceiveVideo/offerToReceiveAudio constraints are explicitly set to
1670// false, the generated m-lines will be a=inactive.
1671TEST_F(PeerConnectionInterfaceTest, CreateSubsequentInactiveOffer) {
1672 FakeConstraints constraints;
1673 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1674 true);
1675 CreatePeerConnection(&constraints);
1676 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1677 CreateAnswerAsLocalDescription();
1678
1679 // At this point we should be receiving stream 1, but not sending anything.
1680 // A new offer would be recvonly, but we'll set the "no receive" constraints
1681 // to make it inactive.
1682 SessionDescriptionInterface* offer;
1683 FakeConstraints offer_constraints;
1684 offer_constraints.AddMandatory(
1685 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo, false);
1686 offer_constraints.AddMandatory(
1687 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio, false);
1688 DoCreateOffer(&offer, &offer_constraints);
1689
1690 const cricket::ContentInfo* video_content =
1691 cricket::GetFirstVideoContent(offer->description());
1692 const cricket::VideoContentDescription* video_desc =
1693 static_cast<const cricket::VideoContentDescription*>(
1694 video_content->description);
1695 ASSERT_EQ(cricket::MD_INACTIVE, video_desc->direction());
1696
1697 const cricket::ContentInfo* audio_content =
1698 cricket::GetFirstAudioContent(offer->description());
1699 const cricket::AudioContentDescription* audio_desc =
1700 static_cast<const cricket::AudioContentDescription*>(
1701 audio_content->description);
1702 ASSERT_EQ(cricket::MD_INACTIVE, audio_desc->direction());
1703}
1704
deadbeef653b8e02015-11-11 12:55:10 -08001705// Test that we can use SetConfiguration to change the ICE servers of the
1706// PortAllocator.
1707TEST_F(PeerConnectionInterfaceTest, SetConfigurationChangesIceServers) {
1708 CreatePeerConnection();
1709
1710 PeerConnectionInterface::RTCConfiguration config;
1711 PeerConnectionInterface::IceServer server;
1712 server.uri = "stun:test_hostname";
1713 config.servers.push_back(server);
1714 EXPECT_TRUE(pc_->SetConfiguration(config));
1715
1716 cricket::FakePortAllocator* allocator =
1717 port_allocator_factory_->last_created_allocator();
1718 EXPECT_EQ(1u, allocator->stun_servers().size());
1719 EXPECT_EQ("test_hostname", allocator->stun_servers().begin()->hostname());
1720}
1721
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722// Test that PeerConnection::Close changes the states to closed and all remote
1723// tracks change state to ended.
1724TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) {
1725 // Initialize a PeerConnection and negotiate local and remote session
1726 // description.
1727 InitiateCall();
1728 ASSERT_EQ(1u, pc_->local_streams()->count());
1729 ASSERT_EQ(1u, pc_->remote_streams()->count());
1730
1731 pc_->Close();
1732
1733 EXPECT_EQ(PeerConnectionInterface::kClosed, pc_->signaling_state());
1734 EXPECT_EQ(PeerConnectionInterface::kIceConnectionClosed,
1735 pc_->ice_connection_state());
1736 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
1737 pc_->ice_gathering_state());
1738
1739 EXPECT_EQ(1u, pc_->local_streams()->count());
1740 EXPECT_EQ(1u, pc_->remote_streams()->count());
1741
1742 scoped_refptr<MediaStreamInterface> remote_stream =
1743 pc_->remote_streams()->at(0);
1744 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1745 remote_stream->GetVideoTracks()[0]->state());
1746 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1747 remote_stream->GetAudioTracks()[0]->state());
1748}
1749
1750// Test that PeerConnection methods fails gracefully after
1751// PeerConnection::Close has been called.
1752TEST_F(PeerConnectionInterfaceTest, CloseAndTestMethods) {
1753 CreatePeerConnection();
1754 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1755 CreateOfferAsRemoteDescription();
1756 CreateAnswerAsLocalDescription();
1757
1758 ASSERT_EQ(1u, pc_->local_streams()->count());
1759 scoped_refptr<MediaStreamInterface> local_stream =
1760 pc_->local_streams()->at(0);
1761
1762 pc_->Close();
1763
1764 pc_->RemoveStream(local_stream);
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001765 EXPECT_FALSE(pc_->AddStream(local_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
1767 ASSERT_FALSE(local_stream->GetAudioTracks().empty());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001768 rtc::scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769 pc_->CreateDtmfSender(local_stream->GetAudioTracks()[0]));
wu@webrtc.org66037362013-08-13 00:09:35 +00001770 EXPECT_TRUE(NULL == dtmf_sender); // local stream has been removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771
1772 EXPECT_TRUE(pc_->CreateDataChannel("test", NULL) == NULL);
1773
1774 EXPECT_TRUE(pc_->local_description() != NULL);
1775 EXPECT_TRUE(pc_->remote_description() != NULL);
1776
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001777 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -07001778 EXPECT_TRUE(DoCreateOffer(offer.use(), nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001779 rtc::scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -07001780 EXPECT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781
1782 std::string sdp;
1783 ASSERT_TRUE(pc_->remote_description()->ToString(&sdp));
1784 SessionDescriptionInterface* remote_offer =
1785 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1786 sdp, NULL);
1787 EXPECT_FALSE(DoSetRemoteDescription(remote_offer));
1788
1789 ASSERT_TRUE(pc_->local_description()->ToString(&sdp));
1790 SessionDescriptionInterface* local_offer =
1791 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1792 sdp, NULL);
1793 EXPECT_FALSE(DoSetLocalDescription(local_offer));
1794}
1795
1796// Test that GetStats can still be called after PeerConnection::Close.
1797TEST_F(PeerConnectionInterfaceTest, CloseAndGetStats) {
1798 InitiateCall();
1799 pc_->Close();
1800 DoGetStats(NULL);
1801}
deadbeefab9b2d12015-10-14 11:33:11 -07001802
1803// NOTE: The series of tests below come from what used to be
1804// mediastreamsignaling_unittest.cc, and are mostly aimed at testing that
1805// setting a remote or local description has the expected effects.
1806
1807// This test verifies that the remote MediaStreams corresponding to a received
1808// SDP string is created. In this test the two separate MediaStreams are
1809// signaled.
1810TEST_F(PeerConnectionInterfaceTest, UpdateRemoteStreams) {
1811 FakeConstraints constraints;
1812 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1813 true);
1814 CreatePeerConnection(&constraints);
1815 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1816
1817 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
1818 EXPECT_TRUE(
1819 CompareStreamCollections(observer_.remote_streams(), reference.get()));
1820 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1821 EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != nullptr);
1822
1823 // Create a session description based on another SDP with another
1824 // MediaStream.
1825 CreateAndSetRemoteOffer(kSdpStringWithStream1And2);
1826
1827 rtc::scoped_refptr<StreamCollection> reference2(CreateStreamCollection(2));
1828 EXPECT_TRUE(
1829 CompareStreamCollections(observer_.remote_streams(), reference2.get()));
1830}
1831
1832// This test verifies that when remote tracks are added/removed from SDP, the
1833// created remote streams are updated appropriately.
1834TEST_F(PeerConnectionInterfaceTest,
1835 AddRemoveTrackFromExistingRemoteMediaStream) {
1836 FakeConstraints constraints;
1837 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1838 true);
1839 CreatePeerConnection(&constraints);
1840 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1;
1841 CreateSessionDescriptionAndReference(1, 1, desc_ms1.accept());
1842 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1.release()));
1843 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1844 reference_collection_));
1845
1846 // Add extra audio and video tracks to the same MediaStream.
1847 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks;
1848 CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.accept());
1849 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1_two_tracks.release()));
1850 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1851 reference_collection_));
1852
1853 // Remove the extra audio and video tracks.
1854 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2;
1855 CreateSessionDescriptionAndReference(1, 1, desc_ms2.accept());
1856 EXPECT_TRUE(DoSetRemoteDescription(desc_ms2.release()));
1857 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1858 reference_collection_));
1859}
1860
1861// This tests that remote tracks are ended if a local session description is set
1862// that rejects the media content type.
1863TEST_F(PeerConnectionInterfaceTest, RejectMediaContent) {
1864 FakeConstraints constraints;
1865 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1866 true);
1867 CreatePeerConnection(&constraints);
1868 // First create and set a remote offer, then reject its video content in our
1869 // answer.
1870 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1871 ASSERT_EQ(1u, observer_.remote_streams()->count());
1872 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1873 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1874 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1875
1876 rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video =
1877 remote_stream->GetVideoTracks()[0];
1878 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state());
1879 rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio =
1880 remote_stream->GetAudioTracks()[0];
1881 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1882
1883 rtc::scoped_ptr<SessionDescriptionInterface> local_answer;
deadbeefc80741f2015-10-22 13:14:45 -07001884 EXPECT_TRUE(DoCreateAnswer(local_answer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001885 cricket::ContentInfo* video_info =
1886 local_answer->description()->GetContentByName("video");
1887 video_info->rejected = true;
1888 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1889 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1890 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1891
1892 // Now create an offer where we reject both video and audio.
1893 rtc::scoped_ptr<SessionDescriptionInterface> local_offer;
deadbeefc80741f2015-10-22 13:14:45 -07001894 EXPECT_TRUE(DoCreateOffer(local_offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001895 video_info = local_offer->description()->GetContentByName("video");
1896 ASSERT_TRUE(video_info != nullptr);
1897 video_info->rejected = true;
1898 cricket::ContentInfo* audio_info =
1899 local_offer->description()->GetContentByName("audio");
1900 ASSERT_TRUE(audio_info != nullptr);
1901 audio_info->rejected = true;
1902 EXPECT_TRUE(DoSetLocalDescription(local_offer.release()));
1903 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1904 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state());
1905}
1906
1907// This tests that we won't crash if the remote track has been removed outside
1908// of PeerConnection and then PeerConnection tries to reject the track.
1909TEST_F(PeerConnectionInterfaceTest, RemoveTrackThenRejectMediaContent) {
1910 FakeConstraints constraints;
1911 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1912 true);
1913 CreatePeerConnection(&constraints);
1914 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1915 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1916 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
1917 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
1918
1919 rtc::scoped_ptr<SessionDescriptionInterface> local_answer(
1920 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
1921 kSdpStringWithStream1, nullptr));
1922 cricket::ContentInfo* video_info =
1923 local_answer->description()->GetContentByName("video");
1924 video_info->rejected = true;
1925 cricket::ContentInfo* audio_info =
1926 local_answer->description()->GetContentByName("audio");
1927 audio_info->rejected = true;
1928 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1929
1930 // No crash is a pass.
1931}
1932
deadbeef5e97fb52015-10-15 12:49:08 -07001933// This tests that if a recvonly remote description is set, no remote streams
1934// will be created, even if the description contains SSRCs/MSIDs.
1935// See: https://code.google.com/p/webrtc/issues/detail?id=5054
1936TEST_F(PeerConnectionInterfaceTest, RecvonlyDescriptionDoesntCreateStream) {
1937 FakeConstraints constraints;
1938 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1939 true);
1940 CreatePeerConnection(&constraints);
1941
1942 std::string recvonly_offer = kSdpStringWithStream1;
1943 rtc::replace_substrs(kSendrecv, strlen(kSendrecv), kRecvonly,
1944 strlen(kRecvonly), &recvonly_offer);
1945 CreateAndSetRemoteOffer(recvonly_offer);
1946
1947 EXPECT_EQ(0u, observer_.remote_streams()->count());
1948}
1949
deadbeefab9b2d12015-10-14 11:33:11 -07001950// This tests that a default MediaStream is created if a remote session
1951// description doesn't contain any streams and no MSID support.
1952// It also tests that the default stream is updated if a video m-line is added
1953// in a subsequent session description.
1954TEST_F(PeerConnectionInterfaceTest, SdpWithoutMsidCreatesDefaultStream) {
1955 FakeConstraints constraints;
1956 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1957 true);
1958 CreatePeerConnection(&constraints);
1959 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
1960
1961 ASSERT_EQ(1u, observer_.remote_streams()->count());
1962 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1963
1964 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
1965 EXPECT_EQ(0u, remote_stream->GetVideoTracks().size());
1966 EXPECT_EQ("default", remote_stream->label());
1967
1968 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
1969 ASSERT_EQ(1u, observer_.remote_streams()->count());
1970 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1971 EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
1972 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1973 EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
1974}
1975
1976// This tests that a default MediaStream is created if a remote session
1977// description doesn't contain any streams and media direction is send only.
1978TEST_F(PeerConnectionInterfaceTest,
1979 SendOnlySdpWithoutMsidCreatesDefaultStream) {
1980 FakeConstraints constraints;
1981 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1982 true);
1983 CreatePeerConnection(&constraints);
1984 CreateAndSetRemoteOffer(kSdpStringSendOnlyWithoutStreams);
1985
1986 ASSERT_EQ(1u, observer_.remote_streams()->count());
1987 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1988
1989 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
1990 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
1991 EXPECT_EQ("default", remote_stream->label());
1992}
1993
1994// This tests that it won't crash when PeerConnection tries to remove
1995// a remote track that as already been removed from the MediaStream.
1996TEST_F(PeerConnectionInterfaceTest, RemoveAlreadyGoneRemoteStream) {
1997 FakeConstraints constraints;
1998 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1999 true);
2000 CreatePeerConnection(&constraints);
2001 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2002 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2003 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
2004 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
2005
2006 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2007
2008 // No crash is a pass.
2009}
2010
2011// This tests that a default MediaStream is created if the remote session
2012// description doesn't contain any streams and don't contain an indication if
2013// MSID is supported.
2014TEST_F(PeerConnectionInterfaceTest,
2015 SdpWithoutMsidAndStreamsCreatesDefaultStream) {
2016 FakeConstraints constraints;
2017 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2018 true);
2019 CreatePeerConnection(&constraints);
2020 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2021
2022 ASSERT_EQ(1u, observer_.remote_streams()->count());
2023 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2024 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
2025 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
2026}
2027
2028// This tests that a default MediaStream is not created if the remote session
2029// description doesn't contain any streams but does support MSID.
2030TEST_F(PeerConnectionInterfaceTest, SdpWithMsidDontCreatesDefaultStream) {
2031 FakeConstraints constraints;
2032 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2033 true);
2034 CreatePeerConnection(&constraints);
2035 CreateAndSetRemoteOffer(kSdpStringWithMsidWithoutStreams);
2036 EXPECT_EQ(0u, observer_.remote_streams()->count());
2037}
2038
deadbeefbda7e0b2015-12-08 17:13:40 -08002039// This tests that when setting a new description, the old default tracks are
2040// not destroyed and recreated.
2041// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5250
2042TEST_F(PeerConnectionInterfaceTest, DefaultTracksNotDestroyedAndRecreated) {
2043 FakeConstraints constraints;
2044 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2045 true);
2046 CreatePeerConnection(&constraints);
2047 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2048
2049 ASSERT_EQ(1u, observer_.remote_streams()->count());
2050 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2051 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2052
2053 // Set the track to "disabled", then set a new description and ensure the
2054 // track is still disabled, which ensures it hasn't been recreated.
2055 remote_stream->GetAudioTracks()[0]->set_enabled(false);
2056 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2057 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2058 EXPECT_FALSE(remote_stream->GetAudioTracks()[0]->enabled());
2059}
2060
deadbeefab9b2d12015-10-14 11:33:11 -07002061// This tests that a default MediaStream is not created if a remote session
2062// description is updated to not have any MediaStreams.
2063TEST_F(PeerConnectionInterfaceTest, VerifyDefaultStreamIsNotCreated) {
2064 FakeConstraints constraints;
2065 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2066 true);
2067 CreatePeerConnection(&constraints);
2068 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2069 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
2070 EXPECT_TRUE(
2071 CompareStreamCollections(observer_.remote_streams(), reference.get()));
2072
2073 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2074 EXPECT_EQ(0u, observer_.remote_streams()->count());
2075}
2076
2077// This tests that an RtpSender is created when the local description is set
2078// after adding a local stream.
2079// TODO(deadbeef): This test and the one below it need to be updated when
2080// an RtpSender's lifetime isn't determined by when a local description is set.
2081TEST_F(PeerConnectionInterfaceTest, LocalDescriptionChanged) {
2082 FakeConstraints constraints;
2083 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2084 true);
2085 CreatePeerConnection(&constraints);
2086 // Create an offer just to ensure we have an identity before we manually
2087 // call SetLocalDescription.
2088 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002089 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002090
2091 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2092 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2093
2094 pc_->AddStream(reference_collection_->at(0));
2095 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2096 auto senders = pc_->GetSenders();
2097 EXPECT_EQ(4u, senders.size());
2098 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2099 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2100 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2101 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2102
2103 // Remove an audio and video track.
deadbeeffac06552015-11-25 11:26:01 -08002104 pc_->RemoveStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002105 rtc::scoped_ptr<SessionDescriptionInterface> desc_2;
2106 CreateSessionDescriptionAndReference(1, 1, desc_2.accept());
deadbeeffac06552015-11-25 11:26:01 -08002107 pc_->AddStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002108 EXPECT_TRUE(DoSetLocalDescription(desc_2.release()));
2109 senders = pc_->GetSenders();
2110 EXPECT_EQ(2u, senders.size());
2111 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2112 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2113 EXPECT_FALSE(ContainsSender(senders, kAudioTracks[1]));
2114 EXPECT_FALSE(ContainsSender(senders, kVideoTracks[1]));
2115}
2116
2117// This tests that an RtpSender is created when the local description is set
2118// before adding a local stream.
2119TEST_F(PeerConnectionInterfaceTest,
2120 AddLocalStreamAfterLocalDescriptionChanged) {
2121 FakeConstraints constraints;
2122 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2123 true);
2124 CreatePeerConnection(&constraints);
2125 // Create an offer just to ensure we have an identity before we manually
2126 // call SetLocalDescription.
2127 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002128 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002129
2130 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2131 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2132
2133 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2134 auto senders = pc_->GetSenders();
2135 EXPECT_EQ(0u, senders.size());
2136
2137 pc_->AddStream(reference_collection_->at(0));
2138 senders = pc_->GetSenders();
2139 EXPECT_EQ(4u, senders.size());
2140 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2141 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2142 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2143 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2144}
2145
2146// This tests that the expected behavior occurs if the SSRC on a local track is
2147// changed when SetLocalDescription is called.
2148TEST_F(PeerConnectionInterfaceTest,
2149 ChangeSsrcOnTrackInLocalSessionDescription) {
2150 FakeConstraints constraints;
2151 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2152 true);
2153 CreatePeerConnection(&constraints);
2154 // Create an offer just to ensure we have an identity before we manually
2155 // call SetLocalDescription.
2156 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002157 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002158
2159 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2160 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2161 std::string sdp;
2162 desc->ToString(&sdp);
2163
2164 pc_->AddStream(reference_collection_->at(0));
2165 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2166 auto senders = pc_->GetSenders();
2167 EXPECT_EQ(2u, senders.size());
2168 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2169 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2170
2171 // Change the ssrc of the audio and video track.
2172 std::string ssrc_org = "a=ssrc:1";
2173 std::string ssrc_to = "a=ssrc:97";
2174 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2175 ssrc_to.length(), &sdp);
2176 ssrc_org = "a=ssrc:2";
2177 ssrc_to = "a=ssrc:98";
2178 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2179 ssrc_to.length(), &sdp);
2180 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2181 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2182 nullptr));
2183
2184 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2185 senders = pc_->GetSenders();
2186 EXPECT_EQ(2u, senders.size());
2187 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2188 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2189 // TODO(deadbeef): Once RtpSenders expose parameters, check that the SSRC
2190 // changed.
2191}
2192
2193// This tests that the expected behavior occurs if a new session description is
2194// set with the same tracks, but on a different MediaStream.
2195TEST_F(PeerConnectionInterfaceTest, SignalSameTracksInSeparateMediaStream) {
2196 FakeConstraints constraints;
2197 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2198 true);
2199 CreatePeerConnection(&constraints);
2200 // Create an offer just to ensure we have an identity before we manually
2201 // call SetLocalDescription.
2202 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002203 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002204
2205 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2206 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2207 std::string sdp;
2208 desc->ToString(&sdp);
2209
2210 pc_->AddStream(reference_collection_->at(0));
2211 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2212 auto senders = pc_->GetSenders();
2213 EXPECT_EQ(2u, senders.size());
2214 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2215 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2216
2217 // Add a new MediaStream but with the same tracks as in the first stream.
2218 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
2219 webrtc::MediaStream::Create(kStreams[1]));
2220 stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]);
2221 stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]);
2222 pc_->AddStream(stream_1);
2223
2224 // Replace msid in the original SDP.
2225 rtc::replace_substrs(kStreams[0], strlen(kStreams[0]), kStreams[1],
2226 strlen(kStreams[1]), &sdp);
2227
2228 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2229 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2230 nullptr));
2231
2232 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2233 senders = pc_->GetSenders();
2234 EXPECT_EQ(2u, senders.size());
2235 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2236 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2237}
2238
2239// The following tests verify that session options are created correctly.
deadbeefc80741f2015-10-22 13:14:45 -07002240// TODO(deadbeef): Convert these tests to be more end-to-end. Instead of
2241// "verify options are converted correctly", should be "pass options into
2242// CreateOffer and verify the correct offer is produced."
deadbeefab9b2d12015-10-14 11:33:11 -07002243
2244TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidAudioOption) {
2245 RTCOfferAnswerOptions rtc_options;
2246 rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
2247
2248 cricket::MediaSessionOptions options;
2249 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2250
2251 rtc_options.offer_to_receive_audio =
2252 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2253 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2254}
2255
2256TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidVideoOption) {
2257 RTCOfferAnswerOptions rtc_options;
2258 rtc_options.offer_to_receive_video = RTCOfferAnswerOptions::kUndefined - 1;
2259
2260 cricket::MediaSessionOptions options;
2261 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2262
2263 rtc_options.offer_to_receive_video =
2264 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2265 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2266}
2267
2268// Test that a MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002269// OfferToReceiveAudio and OfferToReceiveVideo options are set.
deadbeefab9b2d12015-10-14 11:33:11 -07002270TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
2271 RTCOfferAnswerOptions rtc_options;
2272 rtc_options.offer_to_receive_audio = 1;
2273 rtc_options.offer_to_receive_video = 1;
2274
2275 cricket::MediaSessionOptions options;
2276 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2277 EXPECT_TRUE(options.has_audio());
2278 EXPECT_TRUE(options.has_video());
2279 EXPECT_TRUE(options.bundle_enabled);
2280}
2281
2282// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002283// OfferToReceiveAudio is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002284TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudio) {
2285 RTCOfferAnswerOptions rtc_options;
2286 rtc_options.offer_to_receive_audio = 1;
2287
2288 cricket::MediaSessionOptions options;
2289 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2290 EXPECT_TRUE(options.has_audio());
2291 EXPECT_FALSE(options.has_video());
2292 EXPECT_TRUE(options.bundle_enabled);
2293}
2294
2295// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002296// the default OfferOptions are used.
deadbeefab9b2d12015-10-14 11:33:11 -07002297TEST(CreateSessionOptionsTest, GetDefaultMediaSessionOptionsForOffer) {
2298 RTCOfferAnswerOptions rtc_options;
2299
2300 cricket::MediaSessionOptions options;
2301 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
deadbeefc80741f2015-10-22 13:14:45 -07002302 EXPECT_TRUE(options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002303 EXPECT_FALSE(options.has_video());
deadbeefc80741f2015-10-22 13:14:45 -07002304 EXPECT_TRUE(options.bundle_enabled);
deadbeefab9b2d12015-10-14 11:33:11 -07002305 EXPECT_TRUE(options.vad_enabled);
2306 EXPECT_FALSE(options.transport_options.ice_restart);
2307}
2308
2309// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002310// OfferToReceiveVideo is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002311TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithVideo) {
2312 RTCOfferAnswerOptions rtc_options;
2313 rtc_options.offer_to_receive_audio = 0;
2314 rtc_options.offer_to_receive_video = 1;
2315
2316 cricket::MediaSessionOptions options;
2317 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2318 EXPECT_FALSE(options.has_audio());
2319 EXPECT_TRUE(options.has_video());
2320 EXPECT_TRUE(options.bundle_enabled);
2321}
2322
2323// Test that a correct MediaSessionOptions is created for an offer if
2324// UseRtpMux is set to false.
2325TEST(CreateSessionOptionsTest,
2326 GetMediaSessionOptionsForOfferWithBundleDisabled) {
2327 RTCOfferAnswerOptions rtc_options;
2328 rtc_options.offer_to_receive_audio = 1;
2329 rtc_options.offer_to_receive_video = 1;
2330 rtc_options.use_rtp_mux = false;
2331
2332 cricket::MediaSessionOptions options;
2333 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2334 EXPECT_TRUE(options.has_audio());
2335 EXPECT_TRUE(options.has_video());
2336 EXPECT_FALSE(options.bundle_enabled);
2337}
2338
2339// Test that a correct MediaSessionOptions is created to restart ice if
2340// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
2341// have |transport_options.ice_restart| set.
2342TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithIceRestart) {
2343 RTCOfferAnswerOptions rtc_options;
2344 rtc_options.ice_restart = true;
2345
2346 cricket::MediaSessionOptions options;
2347 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2348 EXPECT_TRUE(options.transport_options.ice_restart);
2349
2350 rtc_options = RTCOfferAnswerOptions();
2351 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2352 EXPECT_FALSE(options.transport_options.ice_restart);
2353}
2354
2355// Test that the MediaConstraints in an answer don't affect if audio and video
2356// is offered in an offer but that if kOfferToReceiveAudio or
2357// kOfferToReceiveVideo constraints are true in an offer, the media type will be
2358// included in subsequent answers.
2359TEST(CreateSessionOptionsTest, MediaConstraintsInAnswer) {
2360 FakeConstraints answer_c;
2361 answer_c.SetMandatoryReceiveAudio(true);
2362 answer_c.SetMandatoryReceiveVideo(true);
2363
2364 cricket::MediaSessionOptions answer_options;
2365 EXPECT_TRUE(ParseConstraintsForAnswer(&answer_c, &answer_options));
2366 EXPECT_TRUE(answer_options.has_audio());
2367 EXPECT_TRUE(answer_options.has_video());
2368
deadbeefc80741f2015-10-22 13:14:45 -07002369 RTCOfferAnswerOptions rtc_offer_options;
deadbeefab9b2d12015-10-14 11:33:11 -07002370
2371 cricket::MediaSessionOptions offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002372 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_offer_options, &offer_options));
2373 EXPECT_TRUE(offer_options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002374 EXPECT_FALSE(offer_options.has_video());
2375
deadbeefc80741f2015-10-22 13:14:45 -07002376 RTCOfferAnswerOptions updated_rtc_offer_options;
2377 updated_rtc_offer_options.offer_to_receive_audio = 1;
2378 updated_rtc_offer_options.offer_to_receive_video = 1;
deadbeefab9b2d12015-10-14 11:33:11 -07002379
2380 cricket::MediaSessionOptions updated_offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002381 EXPECT_TRUE(ConvertRtcOptionsForOffer(updated_rtc_offer_options,
deadbeefab9b2d12015-10-14 11:33:11 -07002382 &updated_offer_options));
2383 EXPECT_TRUE(updated_offer_options.has_audio());
2384 EXPECT_TRUE(updated_offer_options.has_video());
2385
2386 // Since an offer has been created with both audio and video, subsequent
2387 // offers and answers should contain both audio and video.
2388 // Answers will only contain the media types that exist in the offer
2389 // regardless of the value of |updated_answer_options.has_audio| and
2390 // |updated_answer_options.has_video|.
2391 FakeConstraints updated_answer_c;
2392 answer_c.SetMandatoryReceiveAudio(false);
2393 answer_c.SetMandatoryReceiveVideo(false);
2394
2395 cricket::MediaSessionOptions updated_answer_options;
2396 EXPECT_TRUE(
2397 ParseConstraintsForAnswer(&updated_answer_c, &updated_answer_options));
2398 EXPECT_TRUE(updated_answer_options.has_audio());
2399 EXPECT_TRUE(updated_answer_options.has_video());
deadbeefab9b2d12015-10-14 11:33:11 -07002400}