blob: 7b49e45874460ffe1dc62bcb1b28582c9bc26ee6 [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/jsepsessiondescription.h"
deadbeefab9b2d12015-10-14 11:33:11 -070033#include "talk/app/webrtc/mediastream.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034#include "talk/app/webrtc/mediastreaminterface.h"
deadbeefab9b2d12015-10-14 11:33:11 -070035#include "talk/app/webrtc/peerconnection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#include "talk/app/webrtc/peerconnectioninterface.h"
deadbeefab9b2d12015-10-14 11:33:11 -070037#include "talk/app/webrtc/rtpreceiverinterface.h"
38#include "talk/app/webrtc/rtpsenderinterface.h"
39#include "talk/app/webrtc/streamcollection.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040#include "talk/app/webrtc/test/fakeconstraints.h"
Henrik Boström5e56c592015-08-11 10:33:13 +020041#include "talk/app/webrtc/test/fakedtlsidentitystore.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042#include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
43#include "talk/app/webrtc/test/testsdpstrings.h"
wu@webrtc.org967bfff2013-09-19 05:49:50 +000044#include "talk/app/webrtc/videosource.h"
deadbeefab9b2d12015-10-14 11:33:11 -070045#include "talk/app/webrtc/videotrack.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000046#include "talk/media/base/fakevideocapturer.h"
47#include "talk/media/sctp/sctpdataengine.h"
48#include "talk/session/media/mediasession.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000049#include "webrtc/base/gunit.h"
50#include "webrtc/base/scoped_ptr.h"
51#include "webrtc/base/ssladapter.h"
52#include "webrtc/base/sslstreamadapter.h"
53#include "webrtc/base/stringutils.h"
54#include "webrtc/base/thread.h"
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -080055#include "webrtc/p2p/client/fakeportallocator.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;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262using webrtc::IceCandidateInterface;
deadbeefc80741f2015-10-22 13:14:45 -0700263using webrtc::MediaConstraintsInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700264using webrtc::MediaStream;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265using webrtc::MediaStreamInterface;
266using webrtc::MediaStreamTrackInterface;
267using webrtc::MockCreateSessionDescriptionObserver;
268using webrtc::MockDataChannelObserver;
269using webrtc::MockSetSessionDescriptionObserver;
270using webrtc::MockStatsObserver;
271using webrtc::PeerConnectionInterface;
272using webrtc::PeerConnectionObserver;
deadbeefab9b2d12015-10-14 11:33:11 -0700273using webrtc::RtpReceiverInterface;
274using webrtc::RtpSenderInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275using webrtc::SdpParseError;
276using webrtc::SessionDescriptionInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700277using webrtc::StreamCollection;
278using webrtc::StreamCollectionInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279using webrtc::VideoSourceInterface;
deadbeefab9b2d12015-10-14 11:33:11 -0700280using webrtc::VideoTrack;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281using webrtc::VideoTrackInterface;
282
deadbeefab9b2d12015-10-14 11:33:11 -0700283typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
284
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285namespace {
286
287// Gets the first ssrc of given content type from the ContentInfo.
288bool GetFirstSsrc(const cricket::ContentInfo* content_info, int* ssrc) {
289 if (!content_info || !ssrc) {
290 return false;
291 }
292 const cricket::MediaContentDescription* media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000293 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 content_info->description);
295 if (!media_desc || media_desc->streams().empty()) {
296 return false;
297 }
298 *ssrc = media_desc->streams().begin()->first_ssrc();
299 return true;
300}
301
302void SetSsrcToZero(std::string* sdp) {
303 const char kSdpSsrcAtribute[] = "a=ssrc:";
304 const char kSdpSsrcAtributeZero[] = "a=ssrc:0";
305 size_t ssrc_pos = 0;
306 while ((ssrc_pos = sdp->find(kSdpSsrcAtribute, ssrc_pos)) !=
307 std::string::npos) {
308 size_t end_ssrc = sdp->find(" ", ssrc_pos);
309 sdp->replace(ssrc_pos, end_ssrc - ssrc_pos, kSdpSsrcAtributeZero);
310 ssrc_pos = end_ssrc;
311 }
312}
313
deadbeefab9b2d12015-10-14 11:33:11 -0700314// Check if |streams| contains the specified track.
315bool ContainsTrack(const std::vector<cricket::StreamParams>& streams,
316 const std::string& stream_label,
317 const std::string& track_id) {
318 for (const cricket::StreamParams& params : streams) {
319 if (params.sync_label == stream_label && params.id == track_id) {
320 return true;
321 }
322 }
323 return false;
324}
325
326// Check if |senders| contains the specified sender, by id.
327bool ContainsSender(
328 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders,
329 const std::string& id) {
330 for (const auto& sender : senders) {
331 if (sender->id() == id) {
332 return true;
333 }
334 }
335 return false;
336}
337
338// Create a collection of streams.
339// CreateStreamCollection(1) creates a collection that
340// correspond to kSdpStringWithStream1.
341// CreateStreamCollection(2) correspond to kSdpStringWithStream1And2.
342rtc::scoped_refptr<StreamCollection> CreateStreamCollection(
343 int number_of_streams) {
344 rtc::scoped_refptr<StreamCollection> local_collection(
345 StreamCollection::Create());
346
347 for (int i = 0; i < number_of_streams; ++i) {
348 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
349 webrtc::MediaStream::Create(kStreams[i]));
350
351 // Add a local audio track.
352 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
353 webrtc::AudioTrack::Create(kAudioTracks[i], nullptr));
354 stream->AddTrack(audio_track);
355
356 // Add a local video track.
357 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
358 webrtc::VideoTrack::Create(kVideoTracks[i], nullptr));
359 stream->AddTrack(video_track);
360
361 local_collection->AddStream(stream);
362 }
363 return local_collection;
364}
365
366// Check equality of StreamCollections.
367bool CompareStreamCollections(StreamCollectionInterface* s1,
368 StreamCollectionInterface* s2) {
369 if (s1 == nullptr || s2 == nullptr || s1->count() != s2->count()) {
370 return false;
371 }
372
373 for (size_t i = 0; i != s1->count(); ++i) {
374 if (s1->at(i)->label() != s2->at(i)->label()) {
375 return false;
376 }
377 webrtc::AudioTrackVector audio_tracks1 = s1->at(i)->GetAudioTracks();
378 webrtc::AudioTrackVector audio_tracks2 = s2->at(i)->GetAudioTracks();
379 webrtc::VideoTrackVector video_tracks1 = s1->at(i)->GetVideoTracks();
380 webrtc::VideoTrackVector video_tracks2 = s2->at(i)->GetVideoTracks();
381
382 if (audio_tracks1.size() != audio_tracks2.size()) {
383 return false;
384 }
385 for (size_t j = 0; j != audio_tracks1.size(); ++j) {
386 if (audio_tracks1[j]->id() != audio_tracks2[j]->id()) {
387 return false;
388 }
389 }
390 if (video_tracks1.size() != video_tracks2.size()) {
391 return false;
392 }
393 for (size_t j = 0; j != video_tracks1.size(); ++j) {
394 if (video_tracks1[j]->id() != video_tracks2[j]->id()) {
395 return false;
396 }
397 }
398 }
399 return true;
400}
401
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402class MockPeerConnectionObserver : public PeerConnectionObserver {
403 public:
deadbeefab9b2d12015-10-14 11:33:11 -0700404 MockPeerConnectionObserver() : remote_streams_(StreamCollection::Create()) {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000405 ~MockPeerConnectionObserver() {
406 }
407 void SetPeerConnectionInterface(PeerConnectionInterface* pc) {
408 pc_ = pc;
409 if (pc) {
410 state_ = pc_->signaling_state();
411 }
412 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000413 virtual void OnSignalingChange(
414 PeerConnectionInterface::SignalingState new_state) {
415 EXPECT_EQ(pc_->signaling_state(), new_state);
416 state_ = new_state;
417 }
418 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
419 virtual void OnStateChange(StateType state_changed) {
420 if (pc_.get() == NULL)
421 return;
422 switch (state_changed) {
423 case kSignalingState:
424 // OnSignalingChange and OnStateChange(kSignalingState) should always
425 // be called approximately simultaneously. To ease testing, we require
426 // that they always be called in that order. This check verifies
427 // that OnSignalingChange has just been called.
428 EXPECT_EQ(pc_->signaling_state(), state_);
429 break;
430 case kIceState:
431 ADD_FAILURE();
432 break;
433 default:
434 ADD_FAILURE();
435 break;
436 }
437 }
deadbeefab9b2d12015-10-14 11:33:11 -0700438
439 MediaStreamInterface* RemoteStream(const std::string& label) {
440 return remote_streams_->find(label);
441 }
442 StreamCollectionInterface* remote_streams() const { return remote_streams_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000443 virtual void OnAddStream(MediaStreamInterface* stream) {
444 last_added_stream_ = stream;
deadbeefab9b2d12015-10-14 11:33:11 -0700445 remote_streams_->AddStream(stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 }
447 virtual void OnRemoveStream(MediaStreamInterface* stream) {
448 last_removed_stream_ = stream;
deadbeefab9b2d12015-10-14 11:33:11 -0700449 remote_streams_->RemoveStream(stream);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000450 }
451 virtual void OnRenegotiationNeeded() {
452 renegotiation_needed_ = true;
453 }
454 virtual void OnDataChannel(DataChannelInterface* data_channel) {
455 last_datachannel_ = data_channel;
456 }
457
458 virtual void OnIceConnectionChange(
459 PeerConnectionInterface::IceConnectionState new_state) {
460 EXPECT_EQ(pc_->ice_connection_state(), new_state);
461 }
462 virtual void OnIceGatheringChange(
463 PeerConnectionInterface::IceGatheringState new_state) {
464 EXPECT_EQ(pc_->ice_gathering_state(), new_state);
465 }
466 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
467 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew,
468 pc_->ice_gathering_state());
469
470 std::string sdp;
471 EXPECT_TRUE(candidate->ToString(&sdp));
472 EXPECT_LT(0u, sdp.size());
473 last_candidate_.reset(webrtc::CreateIceCandidate(candidate->sdp_mid(),
474 candidate->sdp_mline_index(), sdp, NULL));
475 EXPECT_TRUE(last_candidate_.get() != NULL);
476 }
477 // TODO(bemasc): Remove this once callers transition to OnSignalingChange.
478 virtual void OnIceComplete() {
479 ice_complete_ = true;
480 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
481 // be called approximately simultaneously. For ease of testing, this
482 // check additionally requires that they be called in the above order.
483 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
484 pc_->ice_gathering_state());
485 }
486
487 // Returns the label of the last added stream.
488 // Empty string if no stream have been added.
489 std::string GetLastAddedStreamLabel() {
490 if (last_added_stream_.get())
491 return last_added_stream_->label();
492 return "";
493 }
494 std::string GetLastRemovedStreamLabel() {
495 if (last_removed_stream_.get())
496 return last_removed_stream_->label();
497 return "";
498 }
499
500 scoped_refptr<PeerConnectionInterface> pc_;
501 PeerConnectionInterface::SignalingState state_;
502 scoped_ptr<IceCandidateInterface> last_candidate_;
503 scoped_refptr<DataChannelInterface> last_datachannel_;
deadbeefab9b2d12015-10-14 11:33:11 -0700504 rtc::scoped_refptr<StreamCollection> remote_streams_;
505 bool renegotiation_needed_ = false;
506 bool ice_complete_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000507
508 private:
509 scoped_refptr<MediaStreamInterface> last_added_stream_;
510 scoped_refptr<MediaStreamInterface> last_removed_stream_;
511};
512
513} // namespace
deadbeefab9b2d12015-10-14 11:33:11 -0700514
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515class PeerConnectionInterfaceTest : public testing::Test {
516 protected:
517 virtual void SetUp() {
518 pc_factory_ = webrtc::CreatePeerConnectionFactory(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000519 rtc::Thread::Current(), rtc::Thread::Current(), NULL, NULL,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000520 NULL);
521 ASSERT_TRUE(pc_factory_.get() != NULL);
522 }
523
524 void CreatePeerConnection() {
525 CreatePeerConnection("", "", NULL);
526 }
527
528 void CreatePeerConnection(webrtc::MediaConstraintsInterface* constraints) {
529 CreatePeerConnection("", "", constraints);
530 }
531
532 void CreatePeerConnection(const std::string& uri,
533 const std::string& password,
534 webrtc::MediaConstraintsInterface* constraints) {
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800535 PeerConnectionInterface::RTCConfiguration config;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 PeerConnectionInterface::IceServer server;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700537 if (!uri.empty()) {
538 server.uri = uri;
539 server.password = password;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800540 config.servers.push_back(server);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700541 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800543 rtc::scoped_ptr<cricket::FakePortAllocator> port_allocator(
544 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
545 port_allocator_ = port_allocator.get();
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(
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800567 config, constraints, std::move(port_allocator),
kwiberg0eb15ed2015-12-17 03:04:15 -0800568 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) {
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800575 PeerConnectionInterface::RTCConfiguration config;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700576 PeerConnectionInterface::IceServer server;
deadbeef0a6c4ca2015-10-06 11:38:28 -0700577 server.uri = uri;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800578 config.servers.push_back(server);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700579
deadbeef0a6c4ca2015-10-06 11:38:28 -0700580 scoped_refptr<PeerConnectionInterface> pc;
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800581 pc = pc_factory_->CreatePeerConnection(config, nullptr, nullptr, nullptr,
582 &observer_);
583 EXPECT_EQ(nullptr, pc);
deadbeef0a6c4ca2015-10-06 11:38:28 -0700584 }
585
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 void CreatePeerConnectionWithDifferentConfigurations() {
587 CreatePeerConnection(kStunAddressOnly, "", NULL);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800588 EXPECT_EQ(1u, port_allocator_->stun_servers().size());
589 EXPECT_EQ(0u, port_allocator_->turn_servers().size());
590 EXPECT_EQ("address", port_allocator_->stun_servers().begin()->hostname());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 EXPECT_EQ(kDefaultStunPort,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800592 port_allocator_->stun_servers().begin()->port());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000593
deadbeef0a6c4ca2015-10-06 11:38:28 -0700594 CreatePeerConnectionExpectFail(kStunInvalidPort);
595 CreatePeerConnectionExpectFail(kStunAddressPortAndMore1);
596 CreatePeerConnectionExpectFail(kStunAddressPortAndMore2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000597
598 CreatePeerConnection(kTurnIceServerUri, kTurnPassword, NULL);
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800599 EXPECT_EQ(0u, port_allocator_->stun_servers().size());
600 EXPECT_EQ(1u, port_allocator_->turn_servers().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 EXPECT_EQ(kTurnUsername,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800602 port_allocator_->turn_servers()[0].credentials.username);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603 EXPECT_EQ(kTurnPassword,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800604 port_allocator_->turn_servers()[0].credentials.password);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 EXPECT_EQ(kTurnHostname,
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800606 port_allocator_->turn_servers()[0].ports[0].address.hostname());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607 }
608
609 void ReleasePeerConnection() {
610 pc_ = NULL;
611 observer_.SetPeerConnectionInterface(NULL);
612 }
613
deadbeefab9b2d12015-10-14 11:33:11 -0700614 void AddVideoStream(const std::string& label) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 // Create a local stream.
616 scoped_refptr<MediaStreamInterface> stream(
617 pc_factory_->CreateLocalMediaStream(label));
618 scoped_refptr<VideoSourceInterface> video_source(
619 pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer(), NULL));
620 scoped_refptr<VideoTrackInterface> video_track(
621 pc_factory_->CreateVideoTrack(label + "v0", video_source));
622 stream->AddTrack(video_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000623 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
625 observer_.renegotiation_needed_ = false;
626 }
627
628 void AddVoiceStream(const std::string& label) {
629 // Create a local stream.
630 scoped_refptr<MediaStreamInterface> stream(
631 pc_factory_->CreateLocalMediaStream(label));
632 scoped_refptr<AudioTrackInterface> audio_track(
633 pc_factory_->CreateAudioTrack(label + "a0", NULL));
634 stream->AddTrack(audio_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000635 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
637 observer_.renegotiation_needed_ = false;
638 }
639
640 void AddAudioVideoStream(const std::string& stream_label,
641 const std::string& audio_track_label,
642 const std::string& video_track_label) {
643 // Create a local stream.
644 scoped_refptr<MediaStreamInterface> stream(
645 pc_factory_->CreateLocalMediaStream(stream_label));
646 scoped_refptr<AudioTrackInterface> audio_track(
647 pc_factory_->CreateAudioTrack(
648 audio_track_label, static_cast<AudioSourceInterface*>(NULL)));
649 stream->AddTrack(audio_track.get());
650 scoped_refptr<VideoTrackInterface> video_track(
651 pc_factory_->CreateVideoTrack(video_track_label, NULL));
652 stream->AddTrack(video_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000653 EXPECT_TRUE(pc_->AddStream(stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 EXPECT_TRUE_WAIT(observer_.renegotiation_needed_, kTimeout);
655 observer_.renegotiation_needed_ = false;
656 }
657
deadbeefc80741f2015-10-22 13:14:45 -0700658 bool DoCreateOfferAnswer(SessionDescriptionInterface** desc,
659 bool offer,
660 MediaConstraintsInterface* constraints) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000661 rtc::scoped_refptr<MockCreateSessionDescriptionObserver>
662 observer(new rtc::RefCountedObject<
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 MockCreateSessionDescriptionObserver>());
664 if (offer) {
deadbeefc80741f2015-10-22 13:14:45 -0700665 pc_->CreateOffer(observer, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000666 } else {
deadbeefc80741f2015-10-22 13:14:45 -0700667 pc_->CreateAnswer(observer, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 }
669 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
670 *desc = observer->release_desc();
671 return observer->result();
672 }
673
deadbeefc80741f2015-10-22 13:14:45 -0700674 bool DoCreateOffer(SessionDescriptionInterface** desc,
675 MediaConstraintsInterface* constraints) {
676 return DoCreateOfferAnswer(desc, true, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 }
678
deadbeefc80741f2015-10-22 13:14:45 -0700679 bool DoCreateAnswer(SessionDescriptionInterface** desc,
680 MediaConstraintsInterface* constraints) {
681 return DoCreateOfferAnswer(desc, false, constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 }
683
684 bool DoSetSessionDescription(SessionDescriptionInterface* desc, bool local) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000685 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
686 observer(new rtc::RefCountedObject<
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 MockSetSessionDescriptionObserver>());
688 if (local) {
689 pc_->SetLocalDescription(observer, desc);
690 } else {
691 pc_->SetRemoteDescription(observer, desc);
692 }
693 EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
694 return observer->result();
695 }
696
697 bool DoSetLocalDescription(SessionDescriptionInterface* desc) {
698 return DoSetSessionDescription(desc, true);
699 }
700
701 bool DoSetRemoteDescription(SessionDescriptionInterface* desc) {
702 return DoSetSessionDescription(desc, false);
703 }
704
705 // Calls PeerConnection::GetStats and check the return value.
706 // It does not verify the values in the StatReports since a RTCP packet might
707 // be required.
708 bool DoGetStats(MediaStreamTrackInterface* track) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000709 rtc::scoped_refptr<MockStatsObserver> observer(
710 new rtc::RefCountedObject<MockStatsObserver>());
jiayl@webrtc.orgdb41b4d2014-03-03 21:30:06 +0000711 if (!pc_->GetStats(
712 observer, track, PeerConnectionInterface::kStatsOutputLevelStandard))
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 return false;
714 EXPECT_TRUE_WAIT(observer->called(), kTimeout);
715 return observer->called();
716 }
717
718 void InitiateCall() {
719 CreatePeerConnection();
720 // Create a local stream with audio&video tracks.
721 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
722 CreateOfferReceiveAnswer();
723 }
724
725 // Verify that RTP Header extensions has been negotiated for audio and video.
726 void VerifyRemoteRtpHeaderExtensions() {
727 const cricket::MediaContentDescription* desc =
728 cricket::GetFirstAudioContentDescription(
729 pc_->remote_description()->description());
730 ASSERT_TRUE(desc != NULL);
731 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
732
733 desc = cricket::GetFirstVideoContentDescription(
734 pc_->remote_description()->description());
735 ASSERT_TRUE(desc != NULL);
736 EXPECT_GT(desc->rtp_header_extensions().size(), 0u);
737 }
738
739 void CreateOfferAsRemoteDescription() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000740 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700741 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742 std::string sdp;
743 EXPECT_TRUE(offer->ToString(&sdp));
744 SessionDescriptionInterface* remote_offer =
745 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
746 sdp, NULL);
747 EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
748 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
749 }
750
deadbeefab9b2d12015-10-14 11:33:11 -0700751 void CreateAndSetRemoteOffer(const std::string& sdp) {
752 SessionDescriptionInterface* remote_offer =
753 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
754 sdp, nullptr);
755 EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
756 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
757 }
758
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 void CreateAnswerAsLocalDescription() {
760 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -0700761 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000762
763 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
764 // audio codec change, even if the parameter has nothing to do with
765 // receiving. Not all parameters are serialized to SDP.
766 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
767 // the SessionDescription, it is necessary to do that here to in order to
768 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
769 // https://code.google.com/p/webrtc/issues/detail?id=1356
770 std::string sdp;
771 EXPECT_TRUE(answer->ToString(&sdp));
772 SessionDescriptionInterface* new_answer =
773 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
774 sdp, NULL);
775 EXPECT_TRUE(DoSetLocalDescription(new_answer));
776 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
777 }
778
779 void CreatePrAnswerAsLocalDescription() {
780 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -0700781 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000782
783 std::string sdp;
784 EXPECT_TRUE(answer->ToString(&sdp));
785 SessionDescriptionInterface* pr_answer =
786 webrtc::CreateSessionDescription(SessionDescriptionInterface::kPrAnswer,
787 sdp, NULL);
788 EXPECT_TRUE(DoSetLocalDescription(pr_answer));
789 EXPECT_EQ(PeerConnectionInterface::kHaveLocalPrAnswer, observer_.state_);
790 }
791
792 void CreateOfferReceiveAnswer() {
793 CreateOfferAsLocalDescription();
794 std::string sdp;
795 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
796 CreateAnswerAsRemoteDescription(sdp);
797 }
798
799 void CreateOfferAsLocalDescription() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000800 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700801 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
803 // audio codec change, even if the parameter has nothing to do with
804 // receiving. Not all parameters are serialized to SDP.
805 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
806 // the SessionDescription, it is necessary to do that here to in order to
807 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
808 // https://code.google.com/p/webrtc/issues/detail?id=1356
809 std::string sdp;
810 EXPECT_TRUE(offer->ToString(&sdp));
811 SessionDescriptionInterface* new_offer =
812 webrtc::CreateSessionDescription(
813 SessionDescriptionInterface::kOffer,
814 sdp, NULL);
815
816 EXPECT_TRUE(DoSetLocalDescription(new_offer));
817 EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer, observer_.state_);
mallinath@webrtc.org68cbd012014-01-22 00:16:46 +0000818 // Wait for the ice_complete message, so that SDP will have candidates.
819 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000820 }
821
deadbeefab9b2d12015-10-14 11:33:11 -0700822 void CreateAnswerAsRemoteDescription(const std::string& sdp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000823 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
824 SessionDescriptionInterface::kAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700825 EXPECT_TRUE(answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826 EXPECT_TRUE(DoSetRemoteDescription(answer));
827 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
828 }
829
deadbeefab9b2d12015-10-14 11:33:11 -0700830 void CreatePrAnswerAndAnswerAsRemoteDescription(const std::string& sdp) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000831 webrtc::JsepSessionDescription* pr_answer =
832 new webrtc::JsepSessionDescription(
833 SessionDescriptionInterface::kPrAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700834 EXPECT_TRUE(pr_answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 EXPECT_TRUE(DoSetRemoteDescription(pr_answer));
836 EXPECT_EQ(PeerConnectionInterface::kHaveRemotePrAnswer, observer_.state_);
837 webrtc::JsepSessionDescription* answer =
838 new webrtc::JsepSessionDescription(
839 SessionDescriptionInterface::kAnswer);
deadbeefab9b2d12015-10-14 11:33:11 -0700840 EXPECT_TRUE(answer->Initialize(sdp, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000841 EXPECT_TRUE(DoSetRemoteDescription(answer));
842 EXPECT_EQ(PeerConnectionInterface::kStable, observer_.state_);
843 }
844
845 // Help function used for waiting until a the last signaled remote stream has
846 // the same label as |stream_label|. In a few of the tests in this file we
847 // answer with the same session description as we offer and thus we can
848 // check if OnAddStream have been called with the same stream as we offer to
849 // send.
850 void WaitAndVerifyOnAddStream(const std::string& stream_label) {
851 EXPECT_EQ_WAIT(stream_label, observer_.GetLastAddedStreamLabel(), kTimeout);
852 }
853
854 // Creates an offer and applies it as a local session description.
855 // Creates an answer with the same SDP an the offer but removes all lines
856 // that start with a:ssrc"
857 void CreateOfferReceiveAnswerWithoutSsrc() {
858 CreateOfferAsLocalDescription();
859 std::string sdp;
860 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
861 SetSsrcToZero(&sdp);
862 CreateAnswerAsRemoteDescription(sdp);
863 }
864
deadbeefab9b2d12015-10-14 11:33:11 -0700865 // This function creates a MediaStream with label kStreams[0] and
866 // |number_of_audio_tracks| and |number_of_video_tracks| tracks and the
867 // corresponding SessionDescriptionInterface. The SessionDescriptionInterface
868 // is returned in |desc| and the MediaStream is stored in
869 // |reference_collection_|
870 void CreateSessionDescriptionAndReference(
871 size_t number_of_audio_tracks,
872 size_t number_of_video_tracks,
873 SessionDescriptionInterface** desc) {
874 ASSERT_TRUE(desc != nullptr);
875 ASSERT_LE(number_of_audio_tracks, 2u);
876 ASSERT_LE(number_of_video_tracks, 2u);
877
878 reference_collection_ = StreamCollection::Create();
879 std::string sdp_ms1 = std::string(kSdpStringInit);
880
881 std::string mediastream_label = kStreams[0];
882
883 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream(
884 webrtc::MediaStream::Create(mediastream_label));
885 reference_collection_->AddStream(stream);
886
887 if (number_of_audio_tracks > 0) {
888 sdp_ms1 += std::string(kSdpStringAudio);
889 sdp_ms1 += std::string(kSdpStringMs1Audio0);
890 AddAudioTrack(kAudioTracks[0], stream);
891 }
892 if (number_of_audio_tracks > 1) {
893 sdp_ms1 += kSdpStringMs1Audio1;
894 AddAudioTrack(kAudioTracks[1], stream);
895 }
896
897 if (number_of_video_tracks > 0) {
898 sdp_ms1 += std::string(kSdpStringVideo);
899 sdp_ms1 += std::string(kSdpStringMs1Video0);
900 AddVideoTrack(kVideoTracks[0], stream);
901 }
902 if (number_of_video_tracks > 1) {
903 sdp_ms1 += kSdpStringMs1Video1;
904 AddVideoTrack(kVideoTracks[1], stream);
905 }
906
907 *desc = webrtc::CreateSessionDescription(
908 SessionDescriptionInterface::kOffer, sdp_ms1, nullptr);
909 }
910
911 void AddAudioTrack(const std::string& track_id,
912 MediaStreamInterface* stream) {
913 rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
914 webrtc::AudioTrack::Create(track_id, nullptr));
915 ASSERT_TRUE(stream->AddTrack(audio_track));
916 }
917
918 void AddVideoTrack(const std::string& track_id,
919 MediaStreamInterface* stream) {
920 rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track(
921 webrtc::VideoTrack::Create(track_id, nullptr));
922 ASSERT_TRUE(stream->AddTrack(video_track));
923 }
924
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -0800925 cricket::FakePortAllocator* port_allocator_ = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000926 scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
927 scoped_refptr<PeerConnectionInterface> pc_;
928 MockPeerConnectionObserver observer_;
deadbeefab9b2d12015-10-14 11:33:11 -0700929 rtc::scoped_refptr<StreamCollection> reference_collection_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000930};
931
932TEST_F(PeerConnectionInterfaceTest,
933 CreatePeerConnectionWithDifferentConfigurations) {
934 CreatePeerConnectionWithDifferentConfigurations();
935}
936
937TEST_F(PeerConnectionInterfaceTest, AddStreams) {
938 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -0700939 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000940 AddVoiceStream(kStreamLabel2);
941 ASSERT_EQ(2u, pc_->local_streams()->count());
942
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000943 // Test we can add multiple local streams to one peerconnection.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944 scoped_refptr<MediaStreamInterface> stream(
945 pc_factory_->CreateLocalMediaStream(kStreamLabel3));
946 scoped_refptr<AudioTrackInterface> audio_track(
947 pc_factory_->CreateAudioTrack(
948 kStreamLabel3, static_cast<AudioSourceInterface*>(NULL)));
949 stream->AddTrack(audio_track.get());
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +0000950 EXPECT_TRUE(pc_->AddStream(stream));
wu@webrtc.org9dba5252013-08-05 20:36:57 +0000951 EXPECT_EQ(3u, pc_->local_streams()->count());
952
953 // Remove the third stream.
954 pc_->RemoveStream(pc_->local_streams()->at(2));
955 EXPECT_EQ(2u, pc_->local_streams()->count());
956
957 // Remove the second stream.
958 pc_->RemoveStream(pc_->local_streams()->at(1));
959 EXPECT_EQ(1u, pc_->local_streams()->count());
960
961 // Remove the first stream.
962 pc_->RemoveStream(pc_->local_streams()->at(0));
963 EXPECT_EQ(0u, pc_->local_streams()->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964}
965
deadbeefab9b2d12015-10-14 11:33:11 -0700966// Test that the created offer includes streams we added.
967TEST_F(PeerConnectionInterfaceTest, AddedStreamsPresentInOffer) {
968 CreatePeerConnection();
969 AddAudioVideoStream(kStreamLabel1, "audio_track", "video_track");
970 scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -0700971 ASSERT_TRUE(DoCreateOffer(offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -0700972
973 const cricket::ContentInfo* audio_content =
974 cricket::GetFirstAudioContent(offer->description());
975 const cricket::AudioContentDescription* audio_desc =
976 static_cast<const cricket::AudioContentDescription*>(
977 audio_content->description);
978 EXPECT_TRUE(
979 ContainsTrack(audio_desc->streams(), kStreamLabel1, "audio_track"));
980
981 const cricket::ContentInfo* video_content =
982 cricket::GetFirstVideoContent(offer->description());
983 const cricket::VideoContentDescription* video_desc =
984 static_cast<const cricket::VideoContentDescription*>(
985 video_content->description);
986 EXPECT_TRUE(
987 ContainsTrack(video_desc->streams(), kStreamLabel1, "video_track"));
988
989 // Add another stream and ensure the offer includes both the old and new
990 // streams.
991 AddAudioVideoStream(kStreamLabel2, "audio_track2", "video_track2");
deadbeefc80741f2015-10-22 13:14:45 -0700992 ASSERT_TRUE(DoCreateOffer(offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -0700993
994 audio_content = cricket::GetFirstAudioContent(offer->description());
995 audio_desc = static_cast<const cricket::AudioContentDescription*>(
996 audio_content->description);
997 EXPECT_TRUE(
998 ContainsTrack(audio_desc->streams(), kStreamLabel1, "audio_track"));
999 EXPECT_TRUE(
1000 ContainsTrack(audio_desc->streams(), kStreamLabel2, "audio_track2"));
1001
1002 video_content = cricket::GetFirstVideoContent(offer->description());
1003 video_desc = static_cast<const cricket::VideoContentDescription*>(
1004 video_content->description);
1005 EXPECT_TRUE(
1006 ContainsTrack(video_desc->streams(), kStreamLabel1, "video_track"));
1007 EXPECT_TRUE(
1008 ContainsTrack(video_desc->streams(), kStreamLabel2, "video_track2"));
1009}
1010
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001011TEST_F(PeerConnectionInterfaceTest, RemoveStream) {
1012 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001013 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001014 ASSERT_EQ(1u, pc_->local_streams()->count());
1015 pc_->RemoveStream(pc_->local_streams()->at(0));
1016 EXPECT_EQ(0u, pc_->local_streams()->count());
1017}
1018
1019TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) {
1020 InitiateCall();
1021 WaitAndVerifyOnAddStream(kStreamLabel1);
1022 VerifyRemoteRtpHeaderExtensions();
1023}
1024
1025TEST_F(PeerConnectionInterfaceTest, CreateOfferReceivePrAnswerAndAnswer) {
1026 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001027 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001028 CreateOfferAsLocalDescription();
1029 std::string offer;
1030 EXPECT_TRUE(pc_->local_description()->ToString(&offer));
1031 CreatePrAnswerAndAnswerAsRemoteDescription(offer);
1032 WaitAndVerifyOnAddStream(kStreamLabel1);
1033}
1034
1035TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreateAnswer) {
1036 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001037 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001038
1039 CreateOfferAsRemoteDescription();
1040 CreateAnswerAsLocalDescription();
1041
1042 WaitAndVerifyOnAddStream(kStreamLabel1);
1043}
1044
1045TEST_F(PeerConnectionInterfaceTest, ReceiveOfferCreatePrAnswerAndAnswer) {
1046 CreatePeerConnection();
deadbeefab9b2d12015-10-14 11:33:11 -07001047 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001048
1049 CreateOfferAsRemoteDescription();
1050 CreatePrAnswerAsLocalDescription();
1051 CreateAnswerAsLocalDescription();
1052
1053 WaitAndVerifyOnAddStream(kStreamLabel1);
1054}
1055
1056TEST_F(PeerConnectionInterfaceTest, Renegotiate) {
1057 InitiateCall();
1058 ASSERT_EQ(1u, pc_->remote_streams()->count());
1059 pc_->RemoveStream(pc_->local_streams()->at(0));
1060 CreateOfferReceiveAnswer();
1061 EXPECT_EQ(0u, pc_->remote_streams()->count());
deadbeefab9b2d12015-10-14 11:33:11 -07001062 AddVideoStream(kStreamLabel1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001063 CreateOfferReceiveAnswer();
1064}
1065
1066// Tests that after negotiating an audio only call, the respondent can perform a
1067// renegotiation that removes the audio stream.
1068TEST_F(PeerConnectionInterfaceTest, RenegotiateAudioOnly) {
1069 CreatePeerConnection();
1070 AddVoiceStream(kStreamLabel1);
1071 CreateOfferAsRemoteDescription();
1072 CreateAnswerAsLocalDescription();
1073
1074 ASSERT_EQ(1u, pc_->remote_streams()->count());
1075 pc_->RemoveStream(pc_->local_streams()->at(0));
1076 CreateOfferReceiveAnswer();
1077 EXPECT_EQ(0u, pc_->remote_streams()->count());
1078}
1079
1080// Test that candidates are generated and that we can parse our own candidates.
1081TEST_F(PeerConnectionInterfaceTest, IceCandidates) {
1082 CreatePeerConnection();
1083
1084 EXPECT_FALSE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
1085 // SetRemoteDescription takes ownership of offer.
1086 SessionDescriptionInterface* offer = NULL;
deadbeefab9b2d12015-10-14 11:33:11 -07001087 AddVideoStream(kStreamLabel1);
deadbeefc80741f2015-10-22 13:14:45 -07001088 EXPECT_TRUE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001089 EXPECT_TRUE(DoSetRemoteDescription(offer));
1090
1091 // SetLocalDescription takes ownership of answer.
1092 SessionDescriptionInterface* answer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001093 EXPECT_TRUE(DoCreateAnswer(&answer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094 EXPECT_TRUE(DoSetLocalDescription(answer));
1095
1096 EXPECT_TRUE_WAIT(observer_.last_candidate_.get() != NULL, kTimeout);
1097 EXPECT_TRUE_WAIT(observer_.ice_complete_, kTimeout);
1098
1099 EXPECT_TRUE(pc_->AddIceCandidate(observer_.last_candidate_.get()));
1100}
1101
deadbeefab9b2d12015-10-14 11:33:11 -07001102// Test that CreateOffer and CreateAnswer will fail if the track labels are
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001103// not unique.
1104TEST_F(PeerConnectionInterfaceTest, CreateOfferAnswerWithInvalidStream) {
1105 CreatePeerConnection();
1106 // Create a regular offer for the CreateAnswer test later.
1107 SessionDescriptionInterface* offer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001108 EXPECT_TRUE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001109 EXPECT_TRUE(offer != NULL);
1110 delete offer;
1111 offer = NULL;
1112
1113 // Create a local stream with audio&video tracks having same label.
1114 AddAudioVideoStream(kStreamLabel1, "track_label", "track_label");
1115
1116 // Test CreateOffer
deadbeefc80741f2015-10-22 13:14:45 -07001117 EXPECT_FALSE(DoCreateOffer(&offer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001118
1119 // Test CreateAnswer
1120 SessionDescriptionInterface* answer = NULL;
deadbeefc80741f2015-10-22 13:14:45 -07001121 EXPECT_FALSE(DoCreateAnswer(&answer, nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001122}
1123
1124// Test that we will get different SSRCs for each tracks in the offer and answer
1125// we created.
1126TEST_F(PeerConnectionInterfaceTest, SsrcInOfferAnswer) {
1127 CreatePeerConnection();
1128 // Create a local stream with audio&video tracks having different labels.
1129 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1130
1131 // Test CreateOffer
1132 scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -07001133 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001134 int audio_ssrc = 0;
1135 int video_ssrc = 0;
1136 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(offer->description()),
1137 &audio_ssrc));
1138 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(offer->description()),
1139 &video_ssrc));
1140 EXPECT_NE(audio_ssrc, video_ssrc);
1141
1142 // Test CreateAnswer
1143 EXPECT_TRUE(DoSetRemoteDescription(offer.release()));
1144 scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -07001145 ASSERT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001146 audio_ssrc = 0;
1147 video_ssrc = 0;
1148 EXPECT_TRUE(GetFirstSsrc(GetFirstAudioContent(answer->description()),
1149 &audio_ssrc));
1150 EXPECT_TRUE(GetFirstSsrc(GetFirstVideoContent(answer->description()),
1151 &video_ssrc));
1152 EXPECT_NE(audio_ssrc, video_ssrc);
1153}
1154
deadbeefeb459812015-12-15 19:24:43 -08001155// Test that it's possible to call AddTrack on a MediaStream after adding
1156// the stream to a PeerConnection.
1157// TODO(deadbeef): Remove this test once this behavior is no longer supported.
1158TEST_F(PeerConnectionInterfaceTest, AddTrackAfterAddStream) {
1159 CreatePeerConnection();
1160 // Create audio stream and add to PeerConnection.
1161 AddVoiceStream(kStreamLabel1);
1162 MediaStreamInterface* stream = pc_->local_streams()->at(0);
1163
1164 // Add video track to the audio-only stream.
1165 scoped_refptr<VideoTrackInterface> video_track(
1166 pc_factory_->CreateVideoTrack("video_label", nullptr));
1167 stream->AddTrack(video_track.get());
1168
1169 scoped_ptr<SessionDescriptionInterface> offer;
1170 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1171
1172 const cricket::MediaContentDescription* video_desc =
1173 cricket::GetFirstVideoContentDescription(offer->description());
1174 EXPECT_TRUE(video_desc != nullptr);
1175}
1176
1177// Test that it's possible to call RemoveTrack on a MediaStream after adding
1178// the stream to a PeerConnection.
1179// TODO(deadbeef): Remove this test once this behavior is no longer supported.
1180TEST_F(PeerConnectionInterfaceTest, RemoveTrackAfterAddStream) {
1181 CreatePeerConnection();
1182 // Create audio/video stream and add to PeerConnection.
1183 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1184 MediaStreamInterface* stream = pc_->local_streams()->at(0);
1185
1186 // Remove the video track.
1187 stream->RemoveTrack(stream->GetVideoTracks()[0]);
1188
1189 scoped_ptr<SessionDescriptionInterface> offer;
1190 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1191
1192 const cricket::MediaContentDescription* video_desc =
1193 cricket::GetFirstVideoContentDescription(offer->description());
1194 EXPECT_TRUE(video_desc == nullptr);
1195}
1196
deadbeefbd7d8f72015-12-18 16:58:44 -08001197// Test creating a sender with a stream ID, and ensure the ID is populated
1198// in the offer.
1199TEST_F(PeerConnectionInterfaceTest, CreateSenderWithStream) {
1200 CreatePeerConnection();
1201 pc_->CreateSender("video", kStreamLabel1);
1202
1203 scoped_ptr<SessionDescriptionInterface> offer;
1204 ASSERT_TRUE(DoCreateOffer(offer.use(), nullptr));
1205
1206 const cricket::MediaContentDescription* video_desc =
1207 cricket::GetFirstVideoContentDescription(offer->description());
1208 ASSERT_TRUE(video_desc != nullptr);
1209 ASSERT_EQ(1u, video_desc->streams().size());
1210 EXPECT_EQ(kStreamLabel1, video_desc->streams()[0].sync_label);
1211}
1212
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213// Test that we can specify a certain track that we want statistics about.
1214TEST_F(PeerConnectionInterfaceTest, GetStatsForSpecificTrack) {
1215 InitiateCall();
1216 ASSERT_LT(0u, pc_->remote_streams()->count());
1217 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetAudioTracks().size());
1218 scoped_refptr<MediaStreamTrackInterface> remote_audio =
1219 pc_->remote_streams()->at(0)->GetAudioTracks()[0];
1220 EXPECT_TRUE(DoGetStats(remote_audio));
1221
1222 // Remove the stream. Since we are sending to our selves the local
1223 // and the remote stream is the same.
1224 pc_->RemoveStream(pc_->local_streams()->at(0));
1225 // Do a re-negotiation.
1226 CreateOfferReceiveAnswer();
1227
1228 ASSERT_EQ(0u, pc_->remote_streams()->count());
1229
1230 // Test that we still can get statistics for the old track. Even if it is not
1231 // sent any longer.
1232 EXPECT_TRUE(DoGetStats(remote_audio));
1233}
1234
1235// Test that we can get stats on a video track.
1236TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
1237 InitiateCall();
1238 ASSERT_LT(0u, pc_->remote_streams()->count());
1239 ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetVideoTracks().size());
1240 scoped_refptr<MediaStreamTrackInterface> remote_video =
1241 pc_->remote_streams()->at(0)->GetVideoTracks()[0];
1242 EXPECT_TRUE(DoGetStats(remote_video));
1243}
1244
1245// Test that we don't get statistics for an invalid track.
tommi@webrtc.org908f57e2014-07-21 11:44:39 +00001246// TODO(tommi): Fix this test. DoGetStats will return true
1247// for the unknown track (since GetStats is async), but no
1248// data is returned for the track.
1249TEST_F(PeerConnectionInterfaceTest, DISABLED_GetStatsForInvalidTrack) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001250 InitiateCall();
1251 scoped_refptr<AudioTrackInterface> unknown_audio_track(
1252 pc_factory_->CreateAudioTrack("unknown track", NULL));
1253 EXPECT_FALSE(DoGetStats(unknown_audio_track));
1254}
1255
1256// This test setup two RTP data channels in loop back.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257TEST_F(PeerConnectionInterfaceTest, TestDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001258 FakeConstraints constraints;
1259 constraints.SetAllowRtpDataChannels();
1260 CreatePeerConnection(&constraints);
1261 scoped_refptr<DataChannelInterface> data1 =
1262 pc_->CreateDataChannel("test1", NULL);
1263 scoped_refptr<DataChannelInterface> data2 =
1264 pc_->CreateDataChannel("test2", NULL);
1265 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001266 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001268 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 new MockDataChannelObserver(data2));
1270
1271 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1272 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1273 std::string data_to_send1 = "testing testing";
1274 std::string data_to_send2 = "testing something else";
1275 EXPECT_FALSE(data1->Send(DataBuffer(data_to_send1)));
1276
1277 CreateOfferReceiveAnswer();
1278 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1279 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1280
1281 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1282 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1283 EXPECT_TRUE(data1->Send(DataBuffer(data_to_send1)));
1284 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1285
1286 EXPECT_EQ_WAIT(data_to_send1, observer1->last_message(), kTimeout);
1287 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1288
1289 data1->Close();
1290 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1291 CreateOfferReceiveAnswer();
1292 EXPECT_FALSE(observer1->IsOpen());
1293 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1294 EXPECT_TRUE(observer2->IsOpen());
1295
1296 data_to_send2 = "testing something else again";
1297 EXPECT_TRUE(data2->Send(DataBuffer(data_to_send2)));
1298
1299 EXPECT_EQ_WAIT(data_to_send2, observer2->last_message(), kTimeout);
1300}
1301
1302// This test verifies that sendnig binary data over RTP data channels should
1303// fail.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304TEST_F(PeerConnectionInterfaceTest, TestSendBinaryOnRtpDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305 FakeConstraints constraints;
1306 constraints.SetAllowRtpDataChannels();
1307 CreatePeerConnection(&constraints);
1308 scoped_refptr<DataChannelInterface> data1 =
1309 pc_->CreateDataChannel("test1", NULL);
1310 scoped_refptr<DataChannelInterface> data2 =
1311 pc_->CreateDataChannel("test2", NULL);
1312 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001313 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001314 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001315 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316 new MockDataChannelObserver(data2));
1317
1318 EXPECT_EQ(DataChannelInterface::kConnecting, data1->state());
1319 EXPECT_EQ(DataChannelInterface::kConnecting, data2->state());
1320
1321 CreateOfferReceiveAnswer();
1322 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1323 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1324
1325 EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
1326 EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
1327
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001328 rtc::Buffer buffer("test", 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 EXPECT_FALSE(data1->Send(DataBuffer(buffer, true)));
1330}
1331
1332// This test setup a RTP data channels in loop back and test that a channel is
1333// opened even if the remote end answer with a zero SSRC.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001334TEST_F(PeerConnectionInterfaceTest, TestSendOnlyDataChannel) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335 FakeConstraints constraints;
1336 constraints.SetAllowRtpDataChannels();
1337 CreatePeerConnection(&constraints);
1338 scoped_refptr<DataChannelInterface> data1 =
1339 pc_->CreateDataChannel("test1", NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001340 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 new MockDataChannelObserver(data1));
1342
1343 CreateOfferReceiveAnswerWithoutSsrc();
1344
1345 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1346
1347 data1->Close();
1348 EXPECT_EQ(DataChannelInterface::kClosing, data1->state());
1349 CreateOfferReceiveAnswerWithoutSsrc();
1350 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1351 EXPECT_FALSE(observer1->IsOpen());
1352}
1353
1354// This test that if a data channel is added in an answer a receive only channel
1355// channel is created.
1356TEST_F(PeerConnectionInterfaceTest, TestReceiveOnlyDataChannel) {
1357 FakeConstraints constraints;
1358 constraints.SetAllowRtpDataChannels();
1359 CreatePeerConnection(&constraints);
1360
1361 std::string offer_label = "offer_channel";
1362 scoped_refptr<DataChannelInterface> offer_channel =
1363 pc_->CreateDataChannel(offer_label, NULL);
1364
1365 CreateOfferAsLocalDescription();
1366
1367 // Replace the data channel label in the offer and apply it as an answer.
1368 std::string receive_label = "answer_channel";
1369 std::string sdp;
1370 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001371 rtc::replace_substrs(offer_label.c_str(), offer_label.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372 receive_label.c_str(), receive_label.length(),
1373 &sdp);
1374 CreateAnswerAsRemoteDescription(sdp);
1375
1376 // Verify that a new incoming data channel has been created and that
1377 // it is open but can't we written to.
1378 ASSERT_TRUE(observer_.last_datachannel_ != NULL);
1379 DataChannelInterface* received_channel = observer_.last_datachannel_;
1380 EXPECT_EQ(DataChannelInterface::kConnecting, received_channel->state());
1381 EXPECT_EQ(receive_label, received_channel->label());
1382 EXPECT_FALSE(received_channel->Send(DataBuffer("something")));
1383
1384 // Verify that the channel we initially offered has been rejected.
1385 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1386
1387 // Do another offer / answer exchange and verify that the data channel is
1388 // opened.
1389 CreateOfferReceiveAnswer();
1390 EXPECT_EQ_WAIT(DataChannelInterface::kOpen, received_channel->state(),
1391 kTimeout);
1392}
1393
1394// This test that no data channel is returned if a reliable channel is
1395// requested.
1396// TODO(perkj): Remove this test once reliable channels are implemented.
1397TEST_F(PeerConnectionInterfaceTest, CreateReliableRtpDataChannelShouldFail) {
1398 FakeConstraints constraints;
1399 constraints.SetAllowRtpDataChannels();
1400 CreatePeerConnection(&constraints);
1401
1402 std::string label = "test";
1403 webrtc::DataChannelInit config;
1404 config.reliable = true;
1405 scoped_refptr<DataChannelInterface> channel =
1406 pc_->CreateDataChannel(label, &config);
1407 EXPECT_TRUE(channel == NULL);
1408}
1409
deadbeefab9b2d12015-10-14 11:33:11 -07001410// Verifies that duplicated label is not allowed for RTP data channel.
1411TEST_F(PeerConnectionInterfaceTest, RtpDuplicatedLabelNotAllowed) {
1412 FakeConstraints constraints;
1413 constraints.SetAllowRtpDataChannels();
1414 CreatePeerConnection(&constraints);
1415
1416 std::string label = "test";
1417 scoped_refptr<DataChannelInterface> channel =
1418 pc_->CreateDataChannel(label, nullptr);
1419 EXPECT_NE(channel, nullptr);
1420
1421 scoped_refptr<DataChannelInterface> dup_channel =
1422 pc_->CreateDataChannel(label, nullptr);
1423 EXPECT_EQ(dup_channel, nullptr);
1424}
1425
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001426// This tests that a SCTP data channel is returned using different
1427// DataChannelInit configurations.
1428TEST_F(PeerConnectionInterfaceTest, CreateSctpDataChannel) {
1429 FakeConstraints constraints;
1430 constraints.SetAllowDtlsSctpDataChannels();
1431 CreatePeerConnection(&constraints);
1432
1433 webrtc::DataChannelInit config;
1434
1435 scoped_refptr<DataChannelInterface> channel =
1436 pc_->CreateDataChannel("1", &config);
1437 EXPECT_TRUE(channel != NULL);
1438 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001439 EXPECT_TRUE(observer_.renegotiation_needed_);
1440 observer_.renegotiation_needed_ = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001441
1442 config.ordered = false;
1443 channel = pc_->CreateDataChannel("2", &config);
1444 EXPECT_TRUE(channel != NULL);
1445 EXPECT_TRUE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001446 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001447
1448 config.ordered = true;
1449 config.maxRetransmits = 0;
1450 channel = pc_->CreateDataChannel("3", &config);
1451 EXPECT_TRUE(channel != NULL);
1452 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001453 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001454
1455 config.maxRetransmits = -1;
1456 config.maxRetransmitTime = 0;
1457 channel = pc_->CreateDataChannel("4", &config);
1458 EXPECT_TRUE(channel != NULL);
1459 EXPECT_FALSE(channel->reliable());
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001460 EXPECT_FALSE(observer_.renegotiation_needed_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461}
1462
1463// This tests that no data channel is returned if both maxRetransmits and
1464// maxRetransmitTime are set for SCTP data channels.
1465TEST_F(PeerConnectionInterfaceTest,
1466 CreateSctpDataChannelShouldFailForInvalidConfig) {
1467 FakeConstraints constraints;
1468 constraints.SetAllowDtlsSctpDataChannels();
1469 CreatePeerConnection(&constraints);
1470
1471 std::string label = "test";
1472 webrtc::DataChannelInit config;
1473 config.maxRetransmits = 0;
1474 config.maxRetransmitTime = 0;
1475
1476 scoped_refptr<DataChannelInterface> channel =
1477 pc_->CreateDataChannel(label, &config);
1478 EXPECT_TRUE(channel == NULL);
1479}
1480
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001481// The test verifies that creating a SCTP data channel with an id already in use
1482// or out of range should fail.
1483TEST_F(PeerConnectionInterfaceTest,
1484 CreateSctpDataChannelWithInvalidIdShouldFail) {
1485 FakeConstraints constraints;
1486 constraints.SetAllowDtlsSctpDataChannels();
1487 CreatePeerConnection(&constraints);
1488
1489 webrtc::DataChannelInit config;
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001490 scoped_refptr<DataChannelInterface> channel;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001491
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001492 config.id = 1;
1493 channel = pc_->CreateDataChannel("1", &config);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001494 EXPECT_TRUE(channel != NULL);
1495 EXPECT_EQ(1, channel->id());
1496
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497 channel = pc_->CreateDataChannel("x", &config);
1498 EXPECT_TRUE(channel == NULL);
1499
1500 config.id = cricket::kMaxSctpSid;
1501 channel = pc_->CreateDataChannel("max", &config);
1502 EXPECT_TRUE(channel != NULL);
1503 EXPECT_EQ(config.id, channel->id());
1504
1505 config.id = cricket::kMaxSctpSid + 1;
1506 channel = pc_->CreateDataChannel("x", &config);
1507 EXPECT_TRUE(channel == NULL);
1508}
1509
deadbeefab9b2d12015-10-14 11:33:11 -07001510// Verifies that duplicated label is allowed for SCTP data channel.
1511TEST_F(PeerConnectionInterfaceTest, SctpDuplicatedLabelAllowed) {
1512 FakeConstraints constraints;
1513 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1514 true);
1515 CreatePeerConnection(&constraints);
1516
1517 std::string label = "test";
1518 scoped_refptr<DataChannelInterface> channel =
1519 pc_->CreateDataChannel(label, nullptr);
1520 EXPECT_NE(channel, nullptr);
1521
1522 scoped_refptr<DataChannelInterface> dup_channel =
1523 pc_->CreateDataChannel(label, nullptr);
1524 EXPECT_NE(dup_channel, nullptr);
1525}
1526
jiayl@webrtc.org001fd2d2014-05-29 15:31:11 +00001527// This test verifies that OnRenegotiationNeeded is fired for every new RTP
1528// DataChannel.
1529TEST_F(PeerConnectionInterfaceTest, RenegotiationNeededForNewRtpDataChannel) {
1530 FakeConstraints constraints;
1531 constraints.SetAllowRtpDataChannels();
1532 CreatePeerConnection(&constraints);
1533
1534 scoped_refptr<DataChannelInterface> dc1 =
1535 pc_->CreateDataChannel("test1", NULL);
1536 EXPECT_TRUE(observer_.renegotiation_needed_);
1537 observer_.renegotiation_needed_ = false;
1538
1539 scoped_refptr<DataChannelInterface> dc2 =
1540 pc_->CreateDataChannel("test2", NULL);
1541 EXPECT_TRUE(observer_.renegotiation_needed_);
1542}
1543
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544// This test that a data channel closes when a PeerConnection is deleted/closed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545TEST_F(PeerConnectionInterfaceTest, DataChannelCloseWhenPeerConnectionClose) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 FakeConstraints constraints;
1547 constraints.SetAllowRtpDataChannels();
1548 CreatePeerConnection(&constraints);
1549
1550 scoped_refptr<DataChannelInterface> data1 =
1551 pc_->CreateDataChannel("test1", NULL);
1552 scoped_refptr<DataChannelInterface> data2 =
1553 pc_->CreateDataChannel("test2", NULL);
1554 ASSERT_TRUE(data1 != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001555 rtc::scoped_ptr<MockDataChannelObserver> observer1(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556 new MockDataChannelObserver(data1));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001557 rtc::scoped_ptr<MockDataChannelObserver> observer2(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 new MockDataChannelObserver(data2));
1559
1560 CreateOfferReceiveAnswer();
1561 EXPECT_TRUE_WAIT(observer1->IsOpen(), kTimeout);
1562 EXPECT_TRUE_WAIT(observer2->IsOpen(), kTimeout);
1563
1564 ReleasePeerConnection();
1565 EXPECT_EQ(DataChannelInterface::kClosed, data1->state());
1566 EXPECT_EQ(DataChannelInterface::kClosed, data2->state());
1567}
1568
1569// This test that data channels can be rejected in an answer.
1570TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
1571 FakeConstraints constraints;
1572 constraints.SetAllowRtpDataChannels();
1573 CreatePeerConnection(&constraints);
1574
1575 scoped_refptr<DataChannelInterface> offer_channel(
1576 pc_->CreateDataChannel("offer_channel", NULL));
1577
1578 CreateOfferAsLocalDescription();
1579
1580 // Create an answer where the m-line for data channels are rejected.
1581 std::string sdp;
1582 EXPECT_TRUE(pc_->local_description()->ToString(&sdp));
1583 webrtc::JsepSessionDescription* answer = new webrtc::JsepSessionDescription(
1584 SessionDescriptionInterface::kAnswer);
1585 EXPECT_TRUE(answer->Initialize(sdp, NULL));
1586 cricket::ContentInfo* data_info =
1587 answer->description()->GetContentByName("data");
1588 data_info->rejected = true;
1589
1590 DoSetRemoteDescription(answer);
1591 EXPECT_EQ(DataChannelInterface::kClosed, offer_channel->state());
1592}
1593
1594// Test that we can create a session description from an SDP string from
1595// FireFox, use it as a remote session description, generate an answer and use
1596// the answer as a local description.
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001597TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001598 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001599 FakeConstraints constraints;
1600 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1601 true);
1602 CreatePeerConnection(&constraints);
1603 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1604 SessionDescriptionInterface* desc =
1605 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001606 webrtc::kFireFoxSdpOffer, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 EXPECT_TRUE(DoSetSessionDescription(desc, false));
1608 CreateAnswerAsLocalDescription();
1609 ASSERT_TRUE(pc_->local_description() != NULL);
1610 ASSERT_TRUE(pc_->remote_description() != NULL);
1611
1612 const cricket::ContentInfo* content =
1613 cricket::GetFirstAudioContent(pc_->local_description()->description());
1614 ASSERT_TRUE(content != NULL);
1615 EXPECT_FALSE(content->rejected);
1616
1617 content =
1618 cricket::GetFirstVideoContent(pc_->local_description()->description());
1619 ASSERT_TRUE(content != NULL);
1620 EXPECT_FALSE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001621#ifdef HAVE_SCTP
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 content =
1623 cricket::GetFirstDataContent(pc_->local_description()->description());
1624 ASSERT_TRUE(content != NULL);
1625 EXPECT_TRUE(content->rejected);
sergeyu@chromium.orga23f0ca2013-11-13 22:48:52 +00001626#endif
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627}
1628
1629// Test that we can create an audio only offer and receive an answer with a
1630// limited set of audio codecs and receive an updated offer with more audio
1631// codecs, where the added codecs are not supported.
1632TEST_F(PeerConnectionInterfaceTest, ReceiveUpdatedAudioOfferWithBadCodecs) {
1633 CreatePeerConnection();
1634 AddVoiceStream("audio_label");
1635 CreateOfferAsLocalDescription();
1636
1637 SessionDescriptionInterface* answer =
1638 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
jbauchfabe2c92015-07-16 13:43:14 -07001639 webrtc::kAudioSdp, nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640 EXPECT_TRUE(DoSetSessionDescription(answer, false));
1641
1642 SessionDescriptionInterface* updated_offer =
1643 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
jbauchfabe2c92015-07-16 13:43:14 -07001644 webrtc::kAudioSdpWithUnsupportedCodecs,
1645 nullptr);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 EXPECT_TRUE(DoSetSessionDescription(updated_offer, false));
1647 CreateAnswerAsLocalDescription();
1648}
1649
deadbeefc80741f2015-10-22 13:14:45 -07001650// Test that if we're receiving (but not sending) a track, subsequent offers
1651// will have m-lines with a=recvonly.
1652TEST_F(PeerConnectionInterfaceTest, CreateSubsequentRecvOnlyOffer) {
1653 FakeConstraints constraints;
1654 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1655 true);
1656 CreatePeerConnection(&constraints);
1657 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1658 CreateAnswerAsLocalDescription();
1659
1660 // At this point we should be receiving stream 1, but not sending anything.
1661 // A new offer should be recvonly.
1662 SessionDescriptionInterface* offer;
1663 DoCreateOffer(&offer, nullptr);
1664
1665 const cricket::ContentInfo* video_content =
1666 cricket::GetFirstVideoContent(offer->description());
1667 const cricket::VideoContentDescription* video_desc =
1668 static_cast<const cricket::VideoContentDescription*>(
1669 video_content->description);
1670 ASSERT_EQ(cricket::MD_RECVONLY, video_desc->direction());
1671
1672 const cricket::ContentInfo* audio_content =
1673 cricket::GetFirstAudioContent(offer->description());
1674 const cricket::AudioContentDescription* audio_desc =
1675 static_cast<const cricket::AudioContentDescription*>(
1676 audio_content->description);
1677 ASSERT_EQ(cricket::MD_RECVONLY, audio_desc->direction());
1678}
1679
1680// Test that if we're receiving (but not sending) a track, and the
1681// offerToReceiveVideo/offerToReceiveAudio constraints are explicitly set to
1682// false, the generated m-lines will be a=inactive.
1683TEST_F(PeerConnectionInterfaceTest, CreateSubsequentInactiveOffer) {
1684 FakeConstraints constraints;
1685 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1686 true);
1687 CreatePeerConnection(&constraints);
1688 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1689 CreateAnswerAsLocalDescription();
1690
1691 // At this point we should be receiving stream 1, but not sending anything.
1692 // A new offer would be recvonly, but we'll set the "no receive" constraints
1693 // to make it inactive.
1694 SessionDescriptionInterface* offer;
1695 FakeConstraints offer_constraints;
1696 offer_constraints.AddMandatory(
1697 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo, false);
1698 offer_constraints.AddMandatory(
1699 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio, false);
1700 DoCreateOffer(&offer, &offer_constraints);
1701
1702 const cricket::ContentInfo* video_content =
1703 cricket::GetFirstVideoContent(offer->description());
1704 const cricket::VideoContentDescription* video_desc =
1705 static_cast<const cricket::VideoContentDescription*>(
1706 video_content->description);
1707 ASSERT_EQ(cricket::MD_INACTIVE, video_desc->direction());
1708
1709 const cricket::ContentInfo* audio_content =
1710 cricket::GetFirstAudioContent(offer->description());
1711 const cricket::AudioContentDescription* audio_desc =
1712 static_cast<const cricket::AudioContentDescription*>(
1713 audio_content->description);
1714 ASSERT_EQ(cricket::MD_INACTIVE, audio_desc->direction());
1715}
1716
deadbeef653b8e02015-11-11 12:55:10 -08001717// Test that we can use SetConfiguration to change the ICE servers of the
1718// PortAllocator.
1719TEST_F(PeerConnectionInterfaceTest, SetConfigurationChangesIceServers) {
1720 CreatePeerConnection();
1721
1722 PeerConnectionInterface::RTCConfiguration config;
1723 PeerConnectionInterface::IceServer server;
1724 server.uri = "stun:test_hostname";
1725 config.servers.push_back(server);
1726 EXPECT_TRUE(pc_->SetConfiguration(config));
1727
Taylor Brandstetter0c7e9f52015-12-29 14:14:52 -08001728 EXPECT_EQ(1u, port_allocator_->stun_servers().size());
1729 EXPECT_EQ("test_hostname",
1730 port_allocator_->stun_servers().begin()->hostname());
deadbeef653b8e02015-11-11 12:55:10 -08001731}
1732
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733// Test that PeerConnection::Close changes the states to closed and all remote
1734// tracks change state to ended.
1735TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) {
1736 // Initialize a PeerConnection and negotiate local and remote session
1737 // description.
1738 InitiateCall();
1739 ASSERT_EQ(1u, pc_->local_streams()->count());
1740 ASSERT_EQ(1u, pc_->remote_streams()->count());
1741
1742 pc_->Close();
1743
1744 EXPECT_EQ(PeerConnectionInterface::kClosed, pc_->signaling_state());
1745 EXPECT_EQ(PeerConnectionInterface::kIceConnectionClosed,
1746 pc_->ice_connection_state());
1747 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
1748 pc_->ice_gathering_state());
1749
1750 EXPECT_EQ(1u, pc_->local_streams()->count());
1751 EXPECT_EQ(1u, pc_->remote_streams()->count());
1752
1753 scoped_refptr<MediaStreamInterface> remote_stream =
1754 pc_->remote_streams()->at(0);
1755 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1756 remote_stream->GetVideoTracks()[0]->state());
1757 EXPECT_EQ(MediaStreamTrackInterface::kEnded,
1758 remote_stream->GetAudioTracks()[0]->state());
1759}
1760
1761// Test that PeerConnection methods fails gracefully after
1762// PeerConnection::Close has been called.
1763TEST_F(PeerConnectionInterfaceTest, CloseAndTestMethods) {
1764 CreatePeerConnection();
1765 AddAudioVideoStream(kStreamLabel1, "audio_label", "video_label");
1766 CreateOfferAsRemoteDescription();
1767 CreateAnswerAsLocalDescription();
1768
1769 ASSERT_EQ(1u, pc_->local_streams()->count());
1770 scoped_refptr<MediaStreamInterface> local_stream =
1771 pc_->local_streams()->at(0);
1772
1773 pc_->Close();
1774
1775 pc_->RemoveStream(local_stream);
perkj@webrtc.orgc2dd5ee2014-11-04 11:31:29 +00001776 EXPECT_FALSE(pc_->AddStream(local_stream));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777
1778 ASSERT_FALSE(local_stream->GetAudioTracks().empty());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001779 rtc::scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001780 pc_->CreateDtmfSender(local_stream->GetAudioTracks()[0]));
wu@webrtc.org66037362013-08-13 00:09:35 +00001781 EXPECT_TRUE(NULL == dtmf_sender); // local stream has been removed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782
1783 EXPECT_TRUE(pc_->CreateDataChannel("test", NULL) == NULL);
1784
1785 EXPECT_TRUE(pc_->local_description() != NULL);
1786 EXPECT_TRUE(pc_->remote_description() != NULL);
1787
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001788 rtc::scoped_ptr<SessionDescriptionInterface> offer;
deadbeefc80741f2015-10-22 13:14:45 -07001789 EXPECT_TRUE(DoCreateOffer(offer.use(), nullptr));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001790 rtc::scoped_ptr<SessionDescriptionInterface> answer;
deadbeefc80741f2015-10-22 13:14:45 -07001791 EXPECT_TRUE(DoCreateAnswer(answer.use(), nullptr));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792
1793 std::string sdp;
1794 ASSERT_TRUE(pc_->remote_description()->ToString(&sdp));
1795 SessionDescriptionInterface* remote_offer =
1796 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1797 sdp, NULL);
1798 EXPECT_FALSE(DoSetRemoteDescription(remote_offer));
1799
1800 ASSERT_TRUE(pc_->local_description()->ToString(&sdp));
1801 SessionDescriptionInterface* local_offer =
1802 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
1803 sdp, NULL);
1804 EXPECT_FALSE(DoSetLocalDescription(local_offer));
1805}
1806
1807// Test that GetStats can still be called after PeerConnection::Close.
1808TEST_F(PeerConnectionInterfaceTest, CloseAndGetStats) {
1809 InitiateCall();
1810 pc_->Close();
1811 DoGetStats(NULL);
1812}
deadbeefab9b2d12015-10-14 11:33:11 -07001813
1814// NOTE: The series of tests below come from what used to be
1815// mediastreamsignaling_unittest.cc, and are mostly aimed at testing that
1816// setting a remote or local description has the expected effects.
1817
1818// This test verifies that the remote MediaStreams corresponding to a received
1819// SDP string is created. In this test the two separate MediaStreams are
1820// signaled.
1821TEST_F(PeerConnectionInterfaceTest, UpdateRemoteStreams) {
1822 FakeConstraints constraints;
1823 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1824 true);
1825 CreatePeerConnection(&constraints);
1826 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1827
1828 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
1829 EXPECT_TRUE(
1830 CompareStreamCollections(observer_.remote_streams(), reference.get()));
1831 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1832 EXPECT_TRUE(remote_stream->GetVideoTracks()[0]->GetSource() != nullptr);
1833
1834 // Create a session description based on another SDP with another
1835 // MediaStream.
1836 CreateAndSetRemoteOffer(kSdpStringWithStream1And2);
1837
1838 rtc::scoped_refptr<StreamCollection> reference2(CreateStreamCollection(2));
1839 EXPECT_TRUE(
1840 CompareStreamCollections(observer_.remote_streams(), reference2.get()));
1841}
1842
1843// This test verifies that when remote tracks are added/removed from SDP, the
1844// created remote streams are updated appropriately.
1845TEST_F(PeerConnectionInterfaceTest,
1846 AddRemoveTrackFromExistingRemoteMediaStream) {
1847 FakeConstraints constraints;
1848 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1849 true);
1850 CreatePeerConnection(&constraints);
1851 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1;
1852 CreateSessionDescriptionAndReference(1, 1, desc_ms1.accept());
1853 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1.release()));
1854 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1855 reference_collection_));
1856
1857 // Add extra audio and video tracks to the same MediaStream.
1858 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms1_two_tracks;
1859 CreateSessionDescriptionAndReference(2, 2, desc_ms1_two_tracks.accept());
1860 EXPECT_TRUE(DoSetRemoteDescription(desc_ms1_two_tracks.release()));
1861 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1862 reference_collection_));
1863
1864 // Remove the extra audio and video tracks.
1865 rtc::scoped_ptr<SessionDescriptionInterface> desc_ms2;
1866 CreateSessionDescriptionAndReference(1, 1, desc_ms2.accept());
1867 EXPECT_TRUE(DoSetRemoteDescription(desc_ms2.release()));
1868 EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
1869 reference_collection_));
1870}
1871
1872// This tests that remote tracks are ended if a local session description is set
1873// that rejects the media content type.
1874TEST_F(PeerConnectionInterfaceTest, RejectMediaContent) {
1875 FakeConstraints constraints;
1876 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1877 true);
1878 CreatePeerConnection(&constraints);
1879 // First create and set a remote offer, then reject its video content in our
1880 // answer.
1881 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1882 ASSERT_EQ(1u, observer_.remote_streams()->count());
1883 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1884 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1885 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1886
1887 rtc::scoped_refptr<webrtc::VideoTrackInterface> remote_video =
1888 remote_stream->GetVideoTracks()[0];
1889 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_video->state());
1890 rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_audio =
1891 remote_stream->GetAudioTracks()[0];
1892 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1893
1894 rtc::scoped_ptr<SessionDescriptionInterface> local_answer;
deadbeefc80741f2015-10-22 13:14:45 -07001895 EXPECT_TRUE(DoCreateAnswer(local_answer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001896 cricket::ContentInfo* video_info =
1897 local_answer->description()->GetContentByName("video");
1898 video_info->rejected = true;
1899 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1900 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1901 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, remote_audio->state());
1902
1903 // Now create an offer where we reject both video and audio.
1904 rtc::scoped_ptr<SessionDescriptionInterface> local_offer;
deadbeefc80741f2015-10-22 13:14:45 -07001905 EXPECT_TRUE(DoCreateOffer(local_offer.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07001906 video_info = local_offer->description()->GetContentByName("video");
1907 ASSERT_TRUE(video_info != nullptr);
1908 video_info->rejected = true;
1909 cricket::ContentInfo* audio_info =
1910 local_offer->description()->GetContentByName("audio");
1911 ASSERT_TRUE(audio_info != nullptr);
1912 audio_info->rejected = true;
1913 EXPECT_TRUE(DoSetLocalDescription(local_offer.release()));
1914 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_video->state());
1915 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kEnded, remote_audio->state());
1916}
1917
1918// This tests that we won't crash if the remote track has been removed outside
1919// of PeerConnection and then PeerConnection tries to reject the track.
1920TEST_F(PeerConnectionInterfaceTest, RemoveTrackThenRejectMediaContent) {
1921 FakeConstraints constraints;
1922 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1923 true);
1924 CreatePeerConnection(&constraints);
1925 CreateAndSetRemoteOffer(kSdpStringWithStream1);
1926 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1927 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
1928 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
1929
1930 rtc::scoped_ptr<SessionDescriptionInterface> local_answer(
1931 webrtc::CreateSessionDescription(SessionDescriptionInterface::kAnswer,
1932 kSdpStringWithStream1, nullptr));
1933 cricket::ContentInfo* video_info =
1934 local_answer->description()->GetContentByName("video");
1935 video_info->rejected = true;
1936 cricket::ContentInfo* audio_info =
1937 local_answer->description()->GetContentByName("audio");
1938 audio_info->rejected = true;
1939 EXPECT_TRUE(DoSetLocalDescription(local_answer.release()));
1940
1941 // No crash is a pass.
1942}
1943
deadbeef5e97fb52015-10-15 12:49:08 -07001944// This tests that if a recvonly remote description is set, no remote streams
1945// will be created, even if the description contains SSRCs/MSIDs.
1946// See: https://code.google.com/p/webrtc/issues/detail?id=5054
1947TEST_F(PeerConnectionInterfaceTest, RecvonlyDescriptionDoesntCreateStream) {
1948 FakeConstraints constraints;
1949 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1950 true);
1951 CreatePeerConnection(&constraints);
1952
1953 std::string recvonly_offer = kSdpStringWithStream1;
1954 rtc::replace_substrs(kSendrecv, strlen(kSendrecv), kRecvonly,
1955 strlen(kRecvonly), &recvonly_offer);
1956 CreateAndSetRemoteOffer(recvonly_offer);
1957
1958 EXPECT_EQ(0u, observer_.remote_streams()->count());
1959}
1960
deadbeefab9b2d12015-10-14 11:33:11 -07001961// This tests that a default MediaStream is created if a remote session
1962// description doesn't contain any streams and no MSID support.
1963// It also tests that the default stream is updated if a video m-line is added
1964// in a subsequent session description.
1965TEST_F(PeerConnectionInterfaceTest, SdpWithoutMsidCreatesDefaultStream) {
1966 FakeConstraints constraints;
1967 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1968 true);
1969 CreatePeerConnection(&constraints);
1970 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
1971
1972 ASSERT_EQ(1u, observer_.remote_streams()->count());
1973 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1974
1975 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
1976 EXPECT_EQ(0u, remote_stream->GetVideoTracks().size());
1977 EXPECT_EQ("default", remote_stream->label());
1978
1979 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
1980 ASSERT_EQ(1u, observer_.remote_streams()->count());
1981 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
1982 EXPECT_EQ("defaulta0", remote_stream->GetAudioTracks()[0]->id());
1983 ASSERT_EQ(1u, remote_stream->GetVideoTracks().size());
1984 EXPECT_EQ("defaultv0", remote_stream->GetVideoTracks()[0]->id());
1985}
1986
1987// This tests that a default MediaStream is created if a remote session
1988// description doesn't contain any streams and media direction is send only.
1989TEST_F(PeerConnectionInterfaceTest,
1990 SendOnlySdpWithoutMsidCreatesDefaultStream) {
1991 FakeConstraints constraints;
1992 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
1993 true);
1994 CreatePeerConnection(&constraints);
1995 CreateAndSetRemoteOffer(kSdpStringSendOnlyWithoutStreams);
1996
1997 ASSERT_EQ(1u, observer_.remote_streams()->count());
1998 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
1999
2000 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
2001 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
2002 EXPECT_EQ("default", remote_stream->label());
2003}
2004
2005// This tests that it won't crash when PeerConnection tries to remove
2006// a remote track that as already been removed from the MediaStream.
2007TEST_F(PeerConnectionInterfaceTest, RemoveAlreadyGoneRemoteStream) {
2008 FakeConstraints constraints;
2009 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2010 true);
2011 CreatePeerConnection(&constraints);
2012 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2013 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2014 remote_stream->RemoveTrack(remote_stream->GetAudioTracks()[0]);
2015 remote_stream->RemoveTrack(remote_stream->GetVideoTracks()[0]);
2016
2017 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2018
2019 // No crash is a pass.
2020}
2021
2022// This tests that a default MediaStream is created if the remote session
2023// description doesn't contain any streams and don't contain an indication if
2024// MSID is supported.
2025TEST_F(PeerConnectionInterfaceTest,
2026 SdpWithoutMsidAndStreamsCreatesDefaultStream) {
2027 FakeConstraints constraints;
2028 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2029 true);
2030 CreatePeerConnection(&constraints);
2031 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2032
2033 ASSERT_EQ(1u, observer_.remote_streams()->count());
2034 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2035 EXPECT_EQ(1u, remote_stream->GetAudioTracks().size());
2036 EXPECT_EQ(1u, remote_stream->GetVideoTracks().size());
2037}
2038
2039// This tests that a default MediaStream is not created if the remote session
2040// description doesn't contain any streams but does support MSID.
2041TEST_F(PeerConnectionInterfaceTest, SdpWithMsidDontCreatesDefaultStream) {
2042 FakeConstraints constraints;
2043 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2044 true);
2045 CreatePeerConnection(&constraints);
2046 CreateAndSetRemoteOffer(kSdpStringWithMsidWithoutStreams);
2047 EXPECT_EQ(0u, observer_.remote_streams()->count());
2048}
2049
deadbeefbda7e0b2015-12-08 17:13:40 -08002050// This tests that when setting a new description, the old default tracks are
2051// not destroyed and recreated.
2052// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5250
2053TEST_F(PeerConnectionInterfaceTest, DefaultTracksNotDestroyedAndRecreated) {
2054 FakeConstraints constraints;
2055 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2056 true);
2057 CreatePeerConnection(&constraints);
2058 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2059
2060 ASSERT_EQ(1u, observer_.remote_streams()->count());
2061 MediaStreamInterface* remote_stream = observer_.remote_streams()->at(0);
2062 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2063
2064 // Set the track to "disabled", then set a new description and ensure the
2065 // track is still disabled, which ensures it hasn't been recreated.
2066 remote_stream->GetAudioTracks()[0]->set_enabled(false);
2067 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly);
2068 ASSERT_EQ(1u, remote_stream->GetAudioTracks().size());
2069 EXPECT_FALSE(remote_stream->GetAudioTracks()[0]->enabled());
2070}
2071
deadbeefab9b2d12015-10-14 11:33:11 -07002072// This tests that a default MediaStream is not created if a remote session
2073// description is updated to not have any MediaStreams.
2074TEST_F(PeerConnectionInterfaceTest, VerifyDefaultStreamIsNotCreated) {
2075 FakeConstraints constraints;
2076 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2077 true);
2078 CreatePeerConnection(&constraints);
2079 CreateAndSetRemoteOffer(kSdpStringWithStream1);
2080 rtc::scoped_refptr<StreamCollection> reference(CreateStreamCollection(1));
2081 EXPECT_TRUE(
2082 CompareStreamCollections(observer_.remote_streams(), reference.get()));
2083
2084 CreateAndSetRemoteOffer(kSdpStringWithoutStreams);
2085 EXPECT_EQ(0u, observer_.remote_streams()->count());
2086}
2087
2088// This tests that an RtpSender is created when the local description is set
2089// after adding a local stream.
2090// TODO(deadbeef): This test and the one below it need to be updated when
2091// an RtpSender's lifetime isn't determined by when a local description is set.
2092TEST_F(PeerConnectionInterfaceTest, LocalDescriptionChanged) {
2093 FakeConstraints constraints;
2094 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2095 true);
2096 CreatePeerConnection(&constraints);
2097 // Create an offer just to ensure we have an identity before we manually
2098 // call SetLocalDescription.
2099 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002100 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002101
2102 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2103 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2104
2105 pc_->AddStream(reference_collection_->at(0));
2106 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2107 auto senders = pc_->GetSenders();
2108 EXPECT_EQ(4u, senders.size());
2109 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2110 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2111 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2112 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2113
2114 // Remove an audio and video track.
deadbeeffac06552015-11-25 11:26:01 -08002115 pc_->RemoveStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002116 rtc::scoped_ptr<SessionDescriptionInterface> desc_2;
2117 CreateSessionDescriptionAndReference(1, 1, desc_2.accept());
deadbeeffac06552015-11-25 11:26:01 -08002118 pc_->AddStream(reference_collection_->at(0));
deadbeefab9b2d12015-10-14 11:33:11 -07002119 EXPECT_TRUE(DoSetLocalDescription(desc_2.release()));
2120 senders = pc_->GetSenders();
2121 EXPECT_EQ(2u, senders.size());
2122 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2123 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2124 EXPECT_FALSE(ContainsSender(senders, kAudioTracks[1]));
2125 EXPECT_FALSE(ContainsSender(senders, kVideoTracks[1]));
2126}
2127
2128// This tests that an RtpSender is created when the local description is set
2129// before adding a local stream.
2130TEST_F(PeerConnectionInterfaceTest,
2131 AddLocalStreamAfterLocalDescriptionChanged) {
2132 FakeConstraints constraints;
2133 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2134 true);
2135 CreatePeerConnection(&constraints);
2136 // Create an offer just to ensure we have an identity before we manually
2137 // call SetLocalDescription.
2138 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002139 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002140
2141 rtc::scoped_ptr<SessionDescriptionInterface> desc_1;
2142 CreateSessionDescriptionAndReference(2, 2, desc_1.accept());
2143
2144 EXPECT_TRUE(DoSetLocalDescription(desc_1.release()));
2145 auto senders = pc_->GetSenders();
2146 EXPECT_EQ(0u, senders.size());
2147
2148 pc_->AddStream(reference_collection_->at(0));
2149 senders = pc_->GetSenders();
2150 EXPECT_EQ(4u, senders.size());
2151 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2152 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2153 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[1]));
2154 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[1]));
2155}
2156
2157// This tests that the expected behavior occurs if the SSRC on a local track is
2158// changed when SetLocalDescription is called.
2159TEST_F(PeerConnectionInterfaceTest,
2160 ChangeSsrcOnTrackInLocalSessionDescription) {
2161 FakeConstraints constraints;
2162 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2163 true);
2164 CreatePeerConnection(&constraints);
2165 // Create an offer just to ensure we have an identity before we manually
2166 // call SetLocalDescription.
2167 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002168 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002169
2170 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2171 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2172 std::string sdp;
2173 desc->ToString(&sdp);
2174
2175 pc_->AddStream(reference_collection_->at(0));
2176 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2177 auto senders = pc_->GetSenders();
2178 EXPECT_EQ(2u, senders.size());
2179 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2180 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2181
2182 // Change the ssrc of the audio and video track.
2183 std::string ssrc_org = "a=ssrc:1";
2184 std::string ssrc_to = "a=ssrc:97";
2185 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2186 ssrc_to.length(), &sdp);
2187 ssrc_org = "a=ssrc:2";
2188 ssrc_to = "a=ssrc:98";
2189 rtc::replace_substrs(ssrc_org.c_str(), ssrc_org.length(), ssrc_to.c_str(),
2190 ssrc_to.length(), &sdp);
2191 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2192 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2193 nullptr));
2194
2195 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2196 senders = pc_->GetSenders();
2197 EXPECT_EQ(2u, senders.size());
2198 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2199 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2200 // TODO(deadbeef): Once RtpSenders expose parameters, check that the SSRC
2201 // changed.
2202}
2203
2204// This tests that the expected behavior occurs if a new session description is
2205// set with the same tracks, but on a different MediaStream.
2206TEST_F(PeerConnectionInterfaceTest, SignalSameTracksInSeparateMediaStream) {
2207 FakeConstraints constraints;
2208 constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
2209 true);
2210 CreatePeerConnection(&constraints);
2211 // Create an offer just to ensure we have an identity before we manually
2212 // call SetLocalDescription.
2213 rtc::scoped_ptr<SessionDescriptionInterface> throwaway;
deadbeefc80741f2015-10-22 13:14:45 -07002214 ASSERT_TRUE(DoCreateOffer(throwaway.accept(), nullptr));
deadbeefab9b2d12015-10-14 11:33:11 -07002215
2216 rtc::scoped_ptr<SessionDescriptionInterface> desc;
2217 CreateSessionDescriptionAndReference(1, 1, desc.accept());
2218 std::string sdp;
2219 desc->ToString(&sdp);
2220
2221 pc_->AddStream(reference_collection_->at(0));
2222 EXPECT_TRUE(DoSetLocalDescription(desc.release()));
2223 auto senders = pc_->GetSenders();
2224 EXPECT_EQ(2u, senders.size());
2225 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2226 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2227
2228 // Add a new MediaStream but with the same tracks as in the first stream.
2229 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_1(
2230 webrtc::MediaStream::Create(kStreams[1]));
2231 stream_1->AddTrack(reference_collection_->at(0)->GetVideoTracks()[0]);
2232 stream_1->AddTrack(reference_collection_->at(0)->GetAudioTracks()[0]);
2233 pc_->AddStream(stream_1);
2234
2235 // Replace msid in the original SDP.
2236 rtc::replace_substrs(kStreams[0], strlen(kStreams[0]), kStreams[1],
2237 strlen(kStreams[1]), &sdp);
2238
2239 rtc::scoped_ptr<SessionDescriptionInterface> updated_desc(
2240 webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer, sdp,
2241 nullptr));
2242
2243 EXPECT_TRUE(DoSetLocalDescription(updated_desc.release()));
2244 senders = pc_->GetSenders();
2245 EXPECT_EQ(2u, senders.size());
2246 EXPECT_TRUE(ContainsSender(senders, kAudioTracks[0]));
2247 EXPECT_TRUE(ContainsSender(senders, kVideoTracks[0]));
2248}
2249
2250// The following tests verify that session options are created correctly.
deadbeefc80741f2015-10-22 13:14:45 -07002251// TODO(deadbeef): Convert these tests to be more end-to-end. Instead of
2252// "verify options are converted correctly", should be "pass options into
2253// CreateOffer and verify the correct offer is produced."
deadbeefab9b2d12015-10-14 11:33:11 -07002254
2255TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidAudioOption) {
2256 RTCOfferAnswerOptions rtc_options;
2257 rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
2258
2259 cricket::MediaSessionOptions options;
2260 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2261
2262 rtc_options.offer_to_receive_audio =
2263 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2264 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2265}
2266
2267TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidVideoOption) {
2268 RTCOfferAnswerOptions rtc_options;
2269 rtc_options.offer_to_receive_video = RTCOfferAnswerOptions::kUndefined - 1;
2270
2271 cricket::MediaSessionOptions options;
2272 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2273
2274 rtc_options.offer_to_receive_video =
2275 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
2276 EXPECT_FALSE(ConvertRtcOptionsForOffer(rtc_options, &options));
2277}
2278
2279// Test that a MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002280// OfferToReceiveAudio and OfferToReceiveVideo options are set.
deadbeefab9b2d12015-10-14 11:33:11 -07002281TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
2282 RTCOfferAnswerOptions rtc_options;
2283 rtc_options.offer_to_receive_audio = 1;
2284 rtc_options.offer_to_receive_video = 1;
2285
2286 cricket::MediaSessionOptions options;
2287 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2288 EXPECT_TRUE(options.has_audio());
2289 EXPECT_TRUE(options.has_video());
2290 EXPECT_TRUE(options.bundle_enabled);
2291}
2292
2293// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002294// OfferToReceiveAudio is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002295TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudio) {
2296 RTCOfferAnswerOptions rtc_options;
2297 rtc_options.offer_to_receive_audio = 1;
2298
2299 cricket::MediaSessionOptions options;
2300 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2301 EXPECT_TRUE(options.has_audio());
2302 EXPECT_FALSE(options.has_video());
2303 EXPECT_TRUE(options.bundle_enabled);
2304}
2305
2306// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002307// the default OfferOptions are used.
deadbeefab9b2d12015-10-14 11:33:11 -07002308TEST(CreateSessionOptionsTest, GetDefaultMediaSessionOptionsForOffer) {
2309 RTCOfferAnswerOptions rtc_options;
2310
2311 cricket::MediaSessionOptions options;
2312 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
deadbeefc80741f2015-10-22 13:14:45 -07002313 EXPECT_TRUE(options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002314 EXPECT_FALSE(options.has_video());
deadbeefc80741f2015-10-22 13:14:45 -07002315 EXPECT_TRUE(options.bundle_enabled);
deadbeefab9b2d12015-10-14 11:33:11 -07002316 EXPECT_TRUE(options.vad_enabled);
2317 EXPECT_FALSE(options.transport_options.ice_restart);
2318}
2319
2320// Test that a correct MediaSessionOptions is created for an offer if
deadbeefc80741f2015-10-22 13:14:45 -07002321// OfferToReceiveVideo is set.
deadbeefab9b2d12015-10-14 11:33:11 -07002322TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithVideo) {
2323 RTCOfferAnswerOptions rtc_options;
2324 rtc_options.offer_to_receive_audio = 0;
2325 rtc_options.offer_to_receive_video = 1;
2326
2327 cricket::MediaSessionOptions options;
2328 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2329 EXPECT_FALSE(options.has_audio());
2330 EXPECT_TRUE(options.has_video());
2331 EXPECT_TRUE(options.bundle_enabled);
2332}
2333
2334// Test that a correct MediaSessionOptions is created for an offer if
2335// UseRtpMux is set to false.
2336TEST(CreateSessionOptionsTest,
2337 GetMediaSessionOptionsForOfferWithBundleDisabled) {
2338 RTCOfferAnswerOptions rtc_options;
2339 rtc_options.offer_to_receive_audio = 1;
2340 rtc_options.offer_to_receive_video = 1;
2341 rtc_options.use_rtp_mux = false;
2342
2343 cricket::MediaSessionOptions options;
2344 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2345 EXPECT_TRUE(options.has_audio());
2346 EXPECT_TRUE(options.has_video());
2347 EXPECT_FALSE(options.bundle_enabled);
2348}
2349
2350// Test that a correct MediaSessionOptions is created to restart ice if
2351// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
2352// have |transport_options.ice_restart| set.
2353TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithIceRestart) {
2354 RTCOfferAnswerOptions rtc_options;
2355 rtc_options.ice_restart = true;
2356
2357 cricket::MediaSessionOptions options;
2358 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2359 EXPECT_TRUE(options.transport_options.ice_restart);
2360
2361 rtc_options = RTCOfferAnswerOptions();
2362 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_options, &options));
2363 EXPECT_FALSE(options.transport_options.ice_restart);
2364}
2365
2366// Test that the MediaConstraints in an answer don't affect if audio and video
2367// is offered in an offer but that if kOfferToReceiveAudio or
2368// kOfferToReceiveVideo constraints are true in an offer, the media type will be
2369// included in subsequent answers.
2370TEST(CreateSessionOptionsTest, MediaConstraintsInAnswer) {
2371 FakeConstraints answer_c;
2372 answer_c.SetMandatoryReceiveAudio(true);
2373 answer_c.SetMandatoryReceiveVideo(true);
2374
2375 cricket::MediaSessionOptions answer_options;
2376 EXPECT_TRUE(ParseConstraintsForAnswer(&answer_c, &answer_options));
2377 EXPECT_TRUE(answer_options.has_audio());
2378 EXPECT_TRUE(answer_options.has_video());
2379
deadbeefc80741f2015-10-22 13:14:45 -07002380 RTCOfferAnswerOptions rtc_offer_options;
deadbeefab9b2d12015-10-14 11:33:11 -07002381
2382 cricket::MediaSessionOptions offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002383 EXPECT_TRUE(ConvertRtcOptionsForOffer(rtc_offer_options, &offer_options));
2384 EXPECT_TRUE(offer_options.has_audio());
deadbeefab9b2d12015-10-14 11:33:11 -07002385 EXPECT_FALSE(offer_options.has_video());
2386
deadbeefc80741f2015-10-22 13:14:45 -07002387 RTCOfferAnswerOptions updated_rtc_offer_options;
2388 updated_rtc_offer_options.offer_to_receive_audio = 1;
2389 updated_rtc_offer_options.offer_to_receive_video = 1;
deadbeefab9b2d12015-10-14 11:33:11 -07002390
2391 cricket::MediaSessionOptions updated_offer_options;
deadbeefc80741f2015-10-22 13:14:45 -07002392 EXPECT_TRUE(ConvertRtcOptionsForOffer(updated_rtc_offer_options,
deadbeefab9b2d12015-10-14 11:33:11 -07002393 &updated_offer_options));
2394 EXPECT_TRUE(updated_offer_options.has_audio());
2395 EXPECT_TRUE(updated_offer_options.has_video());
2396
2397 // Since an offer has been created with both audio and video, subsequent
2398 // offers and answers should contain both audio and video.
2399 // Answers will only contain the media types that exist in the offer
2400 // regardless of the value of |updated_answer_options.has_audio| and
2401 // |updated_answer_options.has_video|.
2402 FakeConstraints updated_answer_c;
2403 answer_c.SetMandatoryReceiveAudio(false);
2404 answer_c.SetMandatoryReceiveVideo(false);
2405
2406 cricket::MediaSessionOptions updated_answer_options;
2407 EXPECT_TRUE(
2408 ParseConstraintsForAnswer(&updated_answer_c, &updated_answer_options));
2409 EXPECT_TRUE(updated_answer_options.has_audio());
2410 EXPECT_TRUE(updated_answer_options.has_video());
deadbeefab9b2d12015-10-14 11:33:11 -07002411}