2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "api/peer_connection_interface.h"
20 #include "absl/strings/str_replace.h"
21 #include "absl/types/optional.h"
22 #include "api/audio/audio_mixer.h"
23 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
24 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
25 #include "api/call/call_factory_interface.h"
26 #include "api/create_peerconnection_factory.h"
27 #include "api/data_channel_interface.h"
29 #include "api/media_stream_interface.h"
30 #include "api/media_types.h"
31 #include "api/rtc_error.h"
32 #include "api/rtc_event_log/rtc_event_log.h"
33 #include "api/rtc_event_log/rtc_event_log_factory.h"
34 #include "api/rtc_event_log_output.h"
35 #include "api/rtp_receiver_interface.h"
36 #include "api/rtp_sender_interface.h"
37 #include "api/rtp_transceiver_direction.h"
38 #include "api/scoped_refptr.h"
39 #include "api/task_queue/default_task_queue_factory.h"
40 #include "api/transport/field_trial_based_config.h"
41 #include "api/video_codecs/video_decoder_factory_template.h"
42 #include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
43 #include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
44 #include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
45 #include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h"
46 #include "api/video_codecs/video_encoder_factory_template.h"
47 #include "api/video_codecs/video_encoder_factory_template_libaom_av1_adapter.h"
48 #include "api/video_codecs/video_encoder_factory_template_libvpx_vp8_adapter.h"
49 #include "api/video_codecs/video_encoder_factory_template_libvpx_vp9_adapter.h"
50 #include "api/video_codecs/video_encoder_factory_template_open_h264_adapter.h"
51 #include "media/base/codec.h"
52 #include "media/base/media_config.h"
53 #include "media/base/media_engine.h"
54 #include "media/base/stream_params.h"
55 #include "media/engine/webrtc_media_engine.h"
56 #include "media/engine/webrtc_media_engine_defaults.h"
57 #include "media/sctp/sctp_transport_internal.h"
58 #include "modules/audio_device/include/audio_device.h"
59 #include "modules/audio_processing/include/audio_processing.h"
60 #include "p2p/base/fake_port_allocator.h"
61 #include "p2p/base/p2p_constants.h"
62 #include "p2p/base/port.h"
63 #include "p2p/base/port_allocator.h"
64 #include "p2p/base/transport_description.h"
65 #include "p2p/base/transport_info.h"
66 #include "pc/audio_track.h"
67 #include "pc/media_session.h"
68 #include "pc/media_stream.h"
69 #include "pc/peer_connection.h"
70 #include "pc/peer_connection_factory.h"
71 #include "pc/rtp_sender.h"
72 #include "pc/rtp_sender_proxy.h"
73 #include "pc/session_description.h"
74 #include "pc/stream_collection.h"
75 #include "pc/test/fake_audio_capture_module.h"
76 #include "pc/test/fake_rtc_certificate_generator.h"
77 #include "pc/test/fake_video_track_source.h"
78 #include "pc/test/mock_peer_connection_observers.h"
79 #include "pc/test/test_sdp_strings.h"
80 #include "pc/video_track.h"
81 #include "rtc_base/checks.h"
82 #include "rtc_base/gunit.h"
83 #include "rtc_base/rtc_certificate_generator.h"
84 #include "rtc_base/socket_address.h"
85 #include "rtc_base/thread.h"
86 #include "rtc_base/virtual_socket_server.h"
87 #include "test/gmock.h"
88 #include "test/gtest.h"
89 #include "test/scoped_key_value_config.h"
92 #include "pc/test/android_test_initializer.h"
98 static const char kStreamId1
[] = "local_stream_1";
99 static const char kStreamId2
[] = "local_stream_2";
100 static const char kStreamId3
[] = "local_stream_3";
101 static const int kDefaultStunPort
= 3478;
102 static const char kStunAddressOnly
[] = "stun:address";
103 static const char kStunInvalidPort
[] = "stun:address:-1";
104 static const char kStunAddressPortAndMore1
[] = "stun:address:port:more";
105 static const char kStunAddressPortAndMore2
[] = "stun:address:port more";
106 static const char kTurnIceServerUri
[] = "turn:turn.example.org";
107 static const char kTurnUsername
[] = "user";
108 static const char kTurnPassword
[] = "password";
109 static const char kTurnHostname
[] = "turn.example.org";
110 static const uint32_t kTimeout
= 10000U;
112 static const char kStreams
[][8] = {"stream1", "stream2"};
113 static const char kAudioTracks
[][32] = {"audiotrack0", "audiotrack1"};
114 static const char kVideoTracks
[][32] = {"videotrack0", "videotrack1"};
116 static const char kRecvonly
[] = "recvonly";
117 static const char kSendrecv
[] = "sendrecv";
118 constexpr uint64_t kTiebreakerDefault
= 44444;
120 // Reference SDP with a MediaStream with label "stream1" and audio track with
121 // id "audio_1" and a video track with id "video_1;
122 static const char kSdpStringWithStream1PlanB
[] =
124 "o=- 0 0 IN IP4 127.0.0.1\r\n"
127 "m=audio 1 RTP/AVPF 111\r\n"
128 "a=ice-ufrag:e5785931\r\n"
129 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
130 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
131 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
135 "a=rtpmap:111 OPUS/48000/2\r\n"
136 "a=ssrc:1 cname:stream1\r\n"
137 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
138 "m=video 1 RTP/AVPF 120\r\n"
139 "a=ice-ufrag:e5785931\r\n"
140 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
141 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
142 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
146 "a=rtpmap:120 VP8/90000\r\n"
147 "a=ssrc:2 cname:stream1\r\n"
148 "a=ssrc:2 msid:stream1 videotrack0\r\n";
149 // Same string as above but with the MID changed to the Unified Plan default and
150 // a=msid added. This is needed so that this SDP can be used as an answer for a
151 // Unified Plan offer.
152 static const char kSdpStringWithStream1UnifiedPlan
[] =
154 "o=- 0 0 IN IP4 127.0.0.1\r\n"
157 "m=audio 1 RTP/AVPF 111\r\n"
158 "a=ice-ufrag:e5785931\r\n"
159 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
160 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
161 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
165 "a=rtpmap:111 OPUS/48000/2\r\n"
166 "a=msid:stream1 audiotrack0\r\n"
167 "a=ssrc:1 cname:stream1\r\n"
168 "m=video 1 RTP/AVPF 120\r\n"
169 "a=ice-ufrag:e5785931\r\n"
170 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
171 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
172 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
176 "a=rtpmap:120 VP8/90000\r\n"
177 "a=msid:stream1 videotrack0\r\n"
178 "a=ssrc:2 cname:stream1\r\n";
180 // Reference SDP with a MediaStream with label "stream1" and audio track with
182 static const char kSdpStringWithStream1AudioTrackOnly
[] =
184 "o=- 0 0 IN IP4 127.0.0.1\r\n"
187 "m=audio 1 RTP/AVPF 111\r\n"
188 "a=ice-ufrag:e5785931\r\n"
189 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
190 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
191 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
194 "a=rtpmap:111 OPUS/48000/2\r\n"
195 "a=ssrc:1 cname:stream1\r\n"
196 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
199 // Reference SDP with two MediaStreams with label "stream1" and "stream2. Each
200 // MediaStreams have one audio track and one video track.
202 static const char kSdpStringWithStream1And2PlanB
[] =
204 "o=- 0 0 IN IP4 127.0.0.1\r\n"
207 "a=msid-semantic: WMS stream1 stream2\r\n"
208 "m=audio 1 RTP/AVPF 111\r\n"
209 "a=ice-ufrag:e5785931\r\n"
210 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
211 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
212 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
216 "a=rtpmap:111 OPUS/48000/2\r\n"
217 "a=ssrc:1 cname:stream1\r\n"
218 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
219 "a=ssrc:3 cname:stream2\r\n"
220 "a=ssrc:3 msid:stream2 audiotrack1\r\n"
221 "m=video 1 RTP/AVPF 120\r\n"
222 "a=ice-ufrag:e5785931\r\n"
223 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
224 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
225 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
229 "a=rtpmap:120 VP8/0\r\n"
230 "a=ssrc:2 cname:stream1\r\n"
231 "a=ssrc:2 msid:stream1 videotrack0\r\n"
232 "a=ssrc:4 cname:stream2\r\n"
233 "a=ssrc:4 msid:stream2 videotrack1\r\n";
234 static const char kSdpStringWithStream1And2UnifiedPlan
[] =
236 "o=- 0 0 IN IP4 127.0.0.1\r\n"
239 "a=msid-semantic: WMS stream1 stream2\r\n"
240 "m=audio 1 RTP/AVPF 111\r\n"
241 "a=ice-ufrag:e5785931\r\n"
242 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
243 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
244 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
248 "a=rtpmap:111 OPUS/48000/2\r\n"
249 "a=ssrc:1 cname:stream1\r\n"
250 "a=ssrc:1 msid:stream1 audiotrack0\r\n"
251 "m=video 1 RTP/AVPF 120\r\n"
252 "a=ice-ufrag:e5785931\r\n"
253 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
254 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
255 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
259 "a=rtpmap:120 VP8/0\r\n"
260 "a=ssrc:2 cname:stream1\r\n"
261 "a=ssrc:2 msid:stream1 videotrack0\r\n"
262 "m=audio 1 RTP/AVPF 111\r\n"
263 "a=ice-ufrag:e5785931\r\n"
264 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
265 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
266 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
270 "a=rtpmap:111 OPUS/48000/2\r\n"
271 "a=ssrc:3 cname:stream2\r\n"
272 "a=ssrc:3 msid:stream2 audiotrack1\r\n"
273 "m=video 1 RTP/AVPF 120\r\n"
274 "a=ice-ufrag:e5785931\r\n"
275 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
276 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
277 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
281 "a=rtpmap:120 VP8/0\r\n"
282 "a=ssrc:4 cname:stream2\r\n"
283 "a=ssrc:4 msid:stream2 videotrack1\r\n";
285 // Reference SDP without MediaStreams. Msid is not supported.
286 static const char kSdpStringWithoutStreams
[] =
288 "o=- 0 0 IN IP4 127.0.0.1\r\n"
291 "m=audio 1 RTP/AVPF 111\r\n"
292 "a=ice-ufrag:e5785931\r\n"
293 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
294 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
295 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
299 "a=rtpmap:111 OPUS/48000/2\r\n"
300 "m=video 1 RTP/AVPF 120\r\n"
301 "a=ice-ufrag:e5785931\r\n"
302 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
303 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
304 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
308 "a=rtpmap:120 VP8/90000\r\n";
310 // Reference SDP without MediaStreams. Msid is supported.
311 static const char kSdpStringWithMsidWithoutStreams
[] =
313 "o=- 0 0 IN IP4 127.0.0.1\r\n"
316 "a=msid-semantic: WMS\r\n"
317 "m=audio 1 RTP/AVPF 111\r\n"
318 "a=ice-ufrag:e5785931\r\n"
319 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
320 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
321 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
325 "a=rtpmap:111 OPUS/48000/2\r\n"
326 "m=video 1 RTP/AVPF 120\r\n"
327 "a=ice-ufrag:e5785931\r\n"
328 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
329 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
330 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
334 "a=rtpmap:120 VP8/90000\r\n";
336 // Reference SDP without MediaStreams and audio only.
337 static const char kSdpStringWithoutStreamsAudioOnly
[] =
339 "o=- 0 0 IN IP4 127.0.0.1\r\n"
342 "m=audio 1 RTP/AVPF 111\r\n"
343 "a=ice-ufrag:e5785931\r\n"
344 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
345 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
346 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
350 "a=rtpmap:111 OPUS/48000/2\r\n";
352 // Reference SENDONLY SDP without MediaStreams. Msid is not supported.
353 static const char kSdpStringSendOnlyWithoutStreams
[] =
355 "o=- 0 0 IN IP4 127.0.0.1\r\n"
358 "m=audio 1 RTP/AVPF 111\r\n"
359 "a=ice-ufrag:e5785931\r\n"
360 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
361 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
362 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
367 "a=rtpmap:111 OPUS/48000/2\r\n"
368 "m=video 1 RTP/AVPF 120\r\n"
369 "a=ice-ufrag:e5785931\r\n"
370 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
371 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
372 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
377 "a=rtpmap:120 VP8/90000\r\n";
379 static const char kSdpStringInit
[] =
381 "o=- 0 0 IN IP4 127.0.0.1\r\n"
384 "a=msid-semantic: WMS\r\n";
386 static const char kSdpStringAudio
[] =
387 "m=audio 1 RTP/AVPF 111\r\n"
388 "a=ice-ufrag:e5785931\r\n"
389 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
390 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
391 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
395 "a=rtpmap:111 OPUS/48000/2\r\n";
397 static const char kSdpStringVideo
[] =
398 "m=video 1 RTP/AVPF 120\r\n"
399 "a=ice-ufrag:e5785931\r\n"
400 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
401 "a=fingerprint:sha-256 58:AB:6E:F5:F1:E4:57:B7:E9:46:F4:86:04:28:F9:A7:ED:"
402 "BD:AB:AE:40:EF:CE:9A:51:2C:2A:B1:9B:8B:78:84\r\n"
406 "a=rtpmap:120 VP8/90000\r\n";
408 static const char kSdpStringMs1Audio0
[] =
409 "a=ssrc:1 cname:stream1\r\n"
410 "a=ssrc:1 msid:stream1 audiotrack0\r\n";
412 static const char kSdpStringMs1Video0
[] =
413 "a=ssrc:2 cname:stream1\r\n"
414 "a=ssrc:2 msid:stream1 videotrack0\r\n";
416 static const char kSdpStringMs1Audio1
[] =
417 "a=ssrc:3 cname:stream1\r\n"
418 "a=ssrc:3 msid:stream1 audiotrack1\r\n";
420 static const char kSdpStringMs1Video1
[] =
421 "a=ssrc:4 cname:stream1\r\n"
422 "a=ssrc:4 msid:stream1 videotrack1\r\n";
424 static const char kDtlsSdesFallbackSdp
[] =
426 "o=xxxxxx 7 2 IN IP4 0.0.0.0\r\n"
428 "c=IN IP4 0.0.0.0\r\n"
430 "a=group:BUNDLE audio\r\n"
431 "a=msid-semantic: WMS\r\n"
432 "m=audio 1 RTP/SAVPF 0\r\n"
436 "a=ssrc:1 cname:stream1\r\n"
437 "a=ice-ufrag:e5785931\r\n"
438 "a=ice-pwd:36fb7878390db89481c1d46daa4278d8\r\n"
439 "a=rtpmap:0 pcmu/8000\r\n"
440 "a=fingerprint:sha-1 "
441 "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
442 "a=setup:actpass\r\n"
443 "a=crypto:0 AES_CM_128_HMAC_SHA1_80 "
444 "inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 "
445 "dummy_session_params\r\n";
447 class RtcEventLogOutputNull final
: public RtcEventLogOutput
{
449 bool IsActive() const override
{ return true; }
450 bool Write(const absl::string_view
/*output*/) override
{ return true; }
453 using ::cricket::StreamParams
;
455 using ::testing::Exactly
;
456 using ::testing::SizeIs
;
457 using ::testing::Values
;
459 using RTCConfiguration
= PeerConnectionInterface::RTCConfiguration
;
460 using RTCOfferAnswerOptions
= PeerConnectionInterface::RTCOfferAnswerOptions
;
462 // Gets the first ssrc of given content type from the ContentInfo.
463 bool GetFirstSsrc(const cricket::ContentInfo
* content_info
, int* ssrc
) {
464 if (!content_info
|| !ssrc
) {
467 const cricket::MediaContentDescription
* media_desc
=
468 content_info
->media_description();
469 if (!media_desc
|| media_desc
->streams().empty()) {
472 *ssrc
= media_desc
->streams().begin()->first_ssrc();
476 // Get the ufrags out of an SDP blob. Useful for testing ICE restart
478 std::vector
<std::string
> GetUfrags(
479 const webrtc::SessionDescriptionInterface
* desc
) {
480 std::vector
<std::string
> ufrags
;
481 for (const cricket::TransportInfo
& info
:
482 desc
->description()->transport_infos()) {
483 ufrags
.push_back(info
.description
.ice_ufrag
);
488 void SetSsrcToZero(std::string
* sdp
) {
489 const char kSdpSsrcAtribute
[] = "a=ssrc:";
490 const char kSdpSsrcAtributeZero
[] = "a=ssrc:0";
492 while ((ssrc_pos
= sdp
->find(kSdpSsrcAtribute
, ssrc_pos
)) !=
494 size_t end_ssrc
= sdp
->find(" ", ssrc_pos
);
495 sdp
->replace(ssrc_pos
, end_ssrc
- ssrc_pos
, kSdpSsrcAtributeZero
);
500 // Check if `streams` contains the specified track.
501 bool ContainsTrack(const std::vector
<cricket::StreamParams
>& streams
,
502 const std::string
& stream_id
,
503 const std::string
& track_id
) {
504 for (const cricket::StreamParams
& params
: streams
) {
505 if (params
.first_stream_id() == stream_id
&& params
.id
== track_id
) {
512 // Check if `senders` contains the specified sender, by id.
514 const std::vector
<rtc::scoped_refptr
<RtpSenderInterface
>>& senders
,
515 const std::string
& id
) {
516 for (const auto& sender
: senders
) {
517 if (sender
->id() == id
) {
524 // Check if `senders` contains the specified sender, by id and stream id.
526 const std::vector
<rtc::scoped_refptr
<RtpSenderInterface
>>& senders
,
527 const std::string
& id
,
528 const std::string
& stream_id
) {
529 for (const auto& sender
: senders
) {
530 if (sender
->id() == id
&& sender
->stream_ids()[0] == stream_id
) {
537 // Create a collection of streams.
538 // CreateStreamCollection(1) creates a collection that
539 // correspond to kSdpStringWithStream1.
540 // CreateStreamCollection(2) correspond to kSdpStringWithStream1And2.
541 rtc::scoped_refptr
<StreamCollection
> CreateStreamCollection(
542 int number_of_streams
,
543 int tracks_per_stream
) {
544 rtc::scoped_refptr
<StreamCollection
> local_collection(
545 StreamCollection::Create());
547 for (int i
= 0; i
< number_of_streams
; ++i
) {
548 rtc::scoped_refptr
<webrtc::MediaStreamInterface
> stream(
549 webrtc::MediaStream::Create(kStreams
[i
]));
551 for (int j
= 0; j
< tracks_per_stream
; ++j
) {
552 // Add a local audio track.
553 rtc::scoped_refptr
<webrtc::AudioTrackInterface
> audio_track(
554 webrtc::AudioTrack::Create(kAudioTracks
[i
* tracks_per_stream
+ j
],
556 stream
->AddTrack(audio_track
);
558 // Add a local video track.
559 rtc::scoped_refptr
<webrtc::VideoTrackInterface
> video_track(
560 webrtc::VideoTrack::Create(kVideoTracks
[i
* tracks_per_stream
+ j
],
561 webrtc::FakeVideoTrackSource::Create(),
562 rtc::Thread::Current()));
563 stream
->AddTrack(video_track
);
566 local_collection
->AddStream(stream
);
568 return local_collection
;
571 // Check equality of StreamCollections.
572 bool CompareStreamCollections(StreamCollectionInterface
* s1
,
573 StreamCollectionInterface
* s2
) {
574 if (s1
== nullptr || s2
== nullptr || s1
->count() != s2
->count()) {
578 for (size_t i
= 0; i
!= s1
->count(); ++i
) {
579 if (s1
->at(i
)->id() != s2
->at(i
)->id()) {
582 webrtc::AudioTrackVector audio_tracks1
= s1
->at(i
)->GetAudioTracks();
583 webrtc::AudioTrackVector audio_tracks2
= s2
->at(i
)->GetAudioTracks();
584 webrtc::VideoTrackVector video_tracks1
= s1
->at(i
)->GetVideoTracks();
585 webrtc::VideoTrackVector video_tracks2
= s2
->at(i
)->GetVideoTracks();
587 if (audio_tracks1
.size() != audio_tracks2
.size()) {
590 for (size_t j
= 0; j
!= audio_tracks1
.size(); ++j
) {
591 if (audio_tracks1
[j
]->id() != audio_tracks2
[j
]->id()) {
595 if (video_tracks1
.size() != video_tracks2
.size()) {
598 for (size_t j
= 0; j
!= video_tracks1
.size(); ++j
) {
599 if (video_tracks1
[j
]->id() != video_tracks2
[j
]->id()) {
607 // Helper class to test Observer.
608 class MockTrackObserver
: public ObserverInterface
{
610 explicit MockTrackObserver(NotifierInterface
* notifier
)
611 : notifier_(notifier
) {
612 notifier_
->RegisterObserver(this);
615 ~MockTrackObserver() { Unregister(); }
619 notifier_
->UnregisterObserver(this);
624 MOCK_METHOD(void, OnChanged
, (), (override
));
627 NotifierInterface
* notifier_
;
630 // The PeerConnectionMediaConfig tests below verify that configuration and
631 // constraints are propagated into the PeerConnection's MediaConfig. These
632 // settings are intended for MediaChannel constructors, but that is not
633 // exercised by these unittest.
634 class PeerConnectionFactoryForTest
: public webrtc::PeerConnectionFactory
{
636 static rtc::scoped_refptr
<PeerConnectionFactoryForTest
>
637 CreatePeerConnectionFactoryForTest() {
638 PeerConnectionFactoryDependencies dependencies
;
639 dependencies
.worker_thread
= rtc::Thread::Current();
640 dependencies
.network_thread
= rtc::Thread::Current();
641 dependencies
.signaling_thread
= rtc::Thread::Current();
642 dependencies
.task_queue_factory
= CreateDefaultTaskQueueFactory();
643 dependencies
.trials
= std::make_unique
<FieldTrialBasedConfig
>();
644 cricket::MediaEngineDependencies media_deps
;
645 media_deps
.task_queue_factory
= dependencies
.task_queue_factory
.get();
646 // Use fake audio device module since we're only testing the interface
647 // level, and using a real one could make tests flaky when run in parallel.
648 media_deps
.adm
= FakeAudioCaptureModule::Create();
649 SetMediaEngineDefaults(&media_deps
);
650 media_deps
.trials
= dependencies
.trials
.get();
651 dependencies
.media_engine
=
652 cricket::CreateMediaEngine(std::move(media_deps
));
653 dependencies
.call_factory
= webrtc::CreateCallFactory();
654 dependencies
.event_log_factory
= std::make_unique
<RtcEventLogFactory
>(
655 dependencies
.task_queue_factory
.get());
657 return rtc::make_ref_counted
<PeerConnectionFactoryForTest
>(
658 std::move(dependencies
));
661 using PeerConnectionFactory::PeerConnectionFactory
;
664 rtc::scoped_refptr
<FakeAudioCaptureModule
> fake_audio_capture_module_
;
667 // TODO(steveanton): Convert to use the new PeerConnectionWrapper.
668 class PeerConnectionInterfaceBaseTest
: public ::testing::Test
{
670 explicit PeerConnectionInterfaceBaseTest(SdpSemantics sdp_semantics
)
671 : vss_(new rtc::VirtualSocketServer()),
673 sdp_semantics_(sdp_semantics
) {
674 #ifdef WEBRTC_ANDROID
675 webrtc::InitializeAndroidObjects();
679 void SetUp() override
{
680 // Use fake audio capture module since we're only testing the interface
681 // level, and using a real one could make tests flaky when run in parallel.
682 fake_audio_capture_module_
= FakeAudioCaptureModule::Create();
683 pc_factory_
= webrtc::CreatePeerConnectionFactory(
684 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
685 rtc::scoped_refptr
<webrtc::AudioDeviceModule
>(
686 fake_audio_capture_module_
),
687 webrtc::CreateBuiltinAudioEncoderFactory(),
688 webrtc::CreateBuiltinAudioDecoderFactory(),
689 std::make_unique
<webrtc::VideoEncoderFactoryTemplate
<
690 webrtc::LibvpxVp8EncoderTemplateAdapter
,
691 webrtc::LibvpxVp9EncoderTemplateAdapter
,
692 webrtc::OpenH264EncoderTemplateAdapter
,
693 webrtc::LibaomAv1EncoderTemplateAdapter
>>(),
694 std::make_unique
<webrtc::VideoDecoderFactoryTemplate
<
695 webrtc::LibvpxVp8DecoderTemplateAdapter
,
696 webrtc::LibvpxVp9DecoderTemplateAdapter
,
697 webrtc::OpenH264DecoderTemplateAdapter
,
698 webrtc::Dav1dDecoderTemplateAdapter
>>(),
699 nullptr /* audio_mixer */, nullptr /* audio_processing */);
700 ASSERT_TRUE(pc_factory_
);
703 void TearDown() override
{
708 void CreatePeerConnection() {
709 CreatePeerConnection(PeerConnectionInterface::RTCConfiguration());
712 // DTLS does not work in a loopback call, so is disabled for many
713 // tests in this file.
714 void CreatePeerConnectionWithoutDtls() {
715 RTCConfiguration config
;
716 PeerConnectionFactoryInterface::Options options
;
717 options
.disable_encryption
= true;
718 pc_factory_
->SetOptions(options
);
719 CreatePeerConnection(config
);
720 options
.disable_encryption
= false;
721 pc_factory_
->SetOptions(options
);
724 void CreatePeerConnectionWithIceTransportsType(
725 PeerConnectionInterface::IceTransportsType type
) {
726 PeerConnectionInterface::RTCConfiguration config
;
728 return CreatePeerConnection(config
);
731 void CreatePeerConnectionWithIceServer(const std::string
& uri
,
732 const std::string
& username
,
733 const std::string
& password
) {
734 PeerConnectionInterface::RTCConfiguration config
;
735 PeerConnectionInterface::IceServer server
;
737 server
.username
= username
;
738 server
.password
= password
;
739 config
.servers
.push_back(server
);
740 CreatePeerConnection(config
);
743 void CreatePeerConnection(const RTCConfiguration
& config
) {
748 std::unique_ptr
<cricket::FakePortAllocator
> port_allocator(
749 new cricket::FakePortAllocator(
750 rtc::Thread::Current(),
751 std::make_unique
<rtc::BasicPacketSocketFactory
>(vss_
.get()),
753 port_allocator_
= port_allocator
.get();
754 port_allocator_
->SetIceTiebreaker(kTiebreakerDefault
);
756 // Create certificate generator unless DTLS constraint is explicitly set to
758 std::unique_ptr
<rtc::RTCCertificateGeneratorInterface
> cert_generator
;
760 // These won't be used if encryption is turned off, but that's harmless.
761 fake_certificate_generator_
= new FakeRTCCertificateGenerator();
762 cert_generator
.reset(fake_certificate_generator_
);
764 RTCConfiguration modified_config
= config
;
765 modified_config
.sdp_semantics
= sdp_semantics_
;
766 PeerConnectionDependencies
pc_dependencies(&observer_
);
767 pc_dependencies
.cert_generator
= std::move(cert_generator
);
768 pc_dependencies
.allocator
= std::move(port_allocator
);
769 auto result
= pc_factory_
->CreatePeerConnectionOrError(
770 modified_config
, std::move(pc_dependencies
));
771 ASSERT_TRUE(result
.ok());
772 pc_
= result
.MoveValue();
773 observer_
.SetPeerConnectionInterface(pc_
.get());
774 EXPECT_EQ(PeerConnectionInterface::kStable
, observer_
.state_
);
777 void CreatePeerConnectionExpectFail(const std::string
& uri
) {
778 PeerConnectionInterface::RTCConfiguration config
;
779 PeerConnectionInterface::IceServer server
;
781 config
.servers
.push_back(server
);
782 config
.sdp_semantics
= sdp_semantics_
;
783 PeerConnectionDependencies
pc_dependencies(&observer_
);
784 auto result
= pc_factory_
->CreatePeerConnectionOrError(
785 config
, std::move(pc_dependencies
));
786 EXPECT_FALSE(result
.ok());
789 void CreatePeerConnectionExpectFail(
790 PeerConnectionInterface::RTCConfiguration config
) {
791 PeerConnectionInterface::IceServer server
;
792 server
.uri
= kTurnIceServerUri
;
793 server
.password
= kTurnPassword
;
794 config
.servers
.push_back(server
);
795 config
.sdp_semantics
= sdp_semantics_
;
796 PeerConnectionDependencies
pc_dependencies(&observer_
);
797 auto result
= pc_factory_
->CreatePeerConnectionOrError(
798 config
, std::move(pc_dependencies
));
799 EXPECT_FALSE(result
.ok());
802 void CreatePeerConnectionWithDifferentConfigurations() {
803 CreatePeerConnectionWithIceServer(kStunAddressOnly
, "", "");
804 EXPECT_EQ(1u, port_allocator_
->stun_servers().size());
805 EXPECT_EQ(0u, port_allocator_
->turn_servers().size());
806 EXPECT_EQ("address", port_allocator_
->stun_servers().begin()->hostname());
807 EXPECT_EQ(kDefaultStunPort
,
808 port_allocator_
->stun_servers().begin()->port());
810 CreatePeerConnectionExpectFail(kStunInvalidPort
);
811 CreatePeerConnectionExpectFail(kStunAddressPortAndMore1
);
812 CreatePeerConnectionExpectFail(kStunAddressPortAndMore2
);
814 CreatePeerConnectionWithIceServer(kTurnIceServerUri
, kTurnUsername
,
816 EXPECT_EQ(0u, port_allocator_
->stun_servers().size());
817 EXPECT_EQ(1u, port_allocator_
->turn_servers().size());
818 EXPECT_EQ(kTurnUsername
,
819 port_allocator_
->turn_servers()[0].credentials
.username
);
820 EXPECT_EQ(kTurnPassword
,
821 port_allocator_
->turn_servers()[0].credentials
.password
);
822 EXPECT_EQ(kTurnHostname
,
823 port_allocator_
->turn_servers()[0].ports
[0].address
.hostname());
826 void ReleasePeerConnection() {
828 observer_
.SetPeerConnectionInterface(nullptr);
831 rtc::scoped_refptr
<VideoTrackInterface
> CreateVideoTrack(
832 const std::string
& label
) {
833 return pc_factory_
->CreateVideoTrack(FakeVideoTrackSource::Create(), label
);
836 void AddVideoTrack(const std::string
& track_label
,
837 const std::vector
<std::string
>& stream_ids
= {}) {
838 auto sender_or_error
=
839 pc_
->AddTrack(CreateVideoTrack(track_label
), stream_ids
);
840 ASSERT_EQ(RTCErrorType::NONE
, sender_or_error
.error().type());
843 void AddVideoStream(const std::string
& label
) {
844 rtc::scoped_refptr
<MediaStreamInterface
> stream(
845 pc_factory_
->CreateLocalMediaStream(label
));
846 stream
->AddTrack(CreateVideoTrack(label
+ "v0"));
847 ASSERT_TRUE(pc_
->AddStream(stream
.get()));
850 rtc::scoped_refptr
<AudioTrackInterface
> CreateAudioTrack(
851 const std::string
& label
) {
852 return pc_factory_
->CreateAudioTrack(label
, nullptr);
855 void AddAudioTrack(const std::string
& track_label
,
856 const std::vector
<std::string
>& stream_ids
= {}) {
857 auto sender_or_error
=
858 pc_
->AddTrack(CreateAudioTrack(track_label
), stream_ids
);
859 ASSERT_EQ(RTCErrorType::NONE
, sender_or_error
.error().type());
862 void AddAudioStream(const std::string
& label
) {
863 rtc::scoped_refptr
<MediaStreamInterface
> stream(
864 pc_factory_
->CreateLocalMediaStream(label
));
865 stream
->AddTrack(CreateAudioTrack(label
+ "a0"));
866 ASSERT_TRUE(pc_
->AddStream(stream
.get()));
869 void AddAudioVideoStream(const std::string
& stream_id
,
870 const std::string
& audio_track_label
,
871 const std::string
& video_track_label
) {
872 // Create a local stream.
873 rtc::scoped_refptr
<MediaStreamInterface
> stream(
874 pc_factory_
->CreateLocalMediaStream(stream_id
));
875 stream
->AddTrack(CreateAudioTrack(audio_track_label
));
876 stream
->AddTrack(CreateVideoTrack(video_track_label
));
877 ASSERT_TRUE(pc_
->AddStream(stream
.get()));
880 rtc::scoped_refptr
<RtpReceiverInterface
> GetFirstReceiverOfType(
881 cricket::MediaType media_type
) {
882 for (auto receiver
: pc_
->GetReceivers()) {
883 if (receiver
->media_type() == media_type
) {
890 bool DoCreateOfferAnswer(std::unique_ptr
<SessionDescriptionInterface
>* desc
,
891 const RTCOfferAnswerOptions
* options
,
894 rtc::make_ref_counted
<MockCreateSessionDescriptionObserver
>();
896 pc_
->CreateOffer(observer
.get(),
897 options
? *options
: RTCOfferAnswerOptions());
899 pc_
->CreateAnswer(observer
.get(),
900 options
? *options
: RTCOfferAnswerOptions());
902 EXPECT_EQ_WAIT(true, observer
->called(), kTimeout
);
903 *desc
= observer
->MoveDescription();
904 return observer
->result();
907 bool DoCreateOffer(std::unique_ptr
<SessionDescriptionInterface
>* desc
,
908 const RTCOfferAnswerOptions
* options
) {
909 return DoCreateOfferAnswer(desc
, options
, true);
912 bool DoCreateAnswer(std::unique_ptr
<SessionDescriptionInterface
>* desc
,
913 const RTCOfferAnswerOptions
* options
) {
914 return DoCreateOfferAnswer(desc
, options
, false);
917 bool DoSetSessionDescription(
918 std::unique_ptr
<SessionDescriptionInterface
> desc
,
920 auto observer
= rtc::make_ref_counted
<MockSetSessionDescriptionObserver
>();
922 pc_
->SetLocalDescription(observer
.get(), desc
.release());
924 pc_
->SetRemoteDescription(observer
.get(), desc
.release());
926 if (pc_
->signaling_state() != PeerConnectionInterface::kClosed
) {
927 EXPECT_EQ_WAIT(true, observer
->called(), kTimeout
);
929 return observer
->result();
932 bool DoSetLocalDescription(
933 std::unique_ptr
<SessionDescriptionInterface
> desc
) {
934 return DoSetSessionDescription(std::move(desc
), true);
937 bool DoSetRemoteDescription(
938 std::unique_ptr
<SessionDescriptionInterface
> desc
) {
939 return DoSetSessionDescription(std::move(desc
), false);
942 // Calls PeerConnection::GetStats and check the return value.
943 // It does not verify the values in the StatReports since a RTCP packet might
945 bool DoGetStats(MediaStreamTrackInterface
* track
) {
946 auto observer
= rtc::make_ref_counted
<MockStatsObserver
>();
947 if (!pc_
->GetStats(observer
.get(), track
,
948 PeerConnectionInterface::kStatsOutputLevelStandard
))
950 EXPECT_TRUE_WAIT(observer
->called(), kTimeout
);
951 return observer
->called();
954 // Call the standards-compliant GetStats function.
955 bool DoGetRTCStats() {
957 rtc::make_ref_counted
<webrtc::MockRTCStatsCollectorCallback
>();
958 pc_
->GetStats(callback
.get());
959 EXPECT_TRUE_WAIT(callback
->called(), kTimeout
);
960 return callback
->called();
963 void InitiateCall() {
964 CreatePeerConnectionWithoutDtls();
965 // Create a local stream with audio&video tracks.
966 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
967 AddAudioVideoStream(kStreamId1
, "audio_track", "video_track");
969 // Unified Plan does not support AddStream, so just add an audio and video
971 AddAudioTrack(kAudioTracks
[0], {kStreamId1
});
972 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
974 CreateOfferReceiveAnswer();
977 // Verify that RTP Header extensions has been negotiated for audio and video.
978 void VerifyRemoteRtpHeaderExtensions() {
979 const cricket::MediaContentDescription
* desc
=
980 cricket::GetFirstAudioContentDescription(
981 pc_
->remote_description()->description());
982 ASSERT_TRUE(desc
!= nullptr);
983 EXPECT_GT(desc
->rtp_header_extensions().size(), 0u);
985 desc
= cricket::GetFirstVideoContentDescription(
986 pc_
->remote_description()->description());
987 ASSERT_TRUE(desc
!= nullptr);
988 EXPECT_GT(desc
->rtp_header_extensions().size(), 0u);
991 void CreateOfferAsRemoteDescription() {
992 std::unique_ptr
<SessionDescriptionInterface
> offer
;
993 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
995 EXPECT_TRUE(offer
->ToString(&sdp
));
996 std::unique_ptr
<SessionDescriptionInterface
> remote_offer(
997 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
998 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_offer
)));
999 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer
, observer_
.state_
);
1002 void CreateAndSetRemoteOffer(const std::string
& sdp
) {
1003 std::unique_ptr
<SessionDescriptionInterface
> remote_offer(
1004 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
1005 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_offer
)));
1006 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer
, observer_
.state_
);
1009 void CreateAnswerAsLocalDescription() {
1010 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1011 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
1013 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
1014 // audio codec change, even if the parameter has nothing to do with
1015 // receiving. Not all parameters are serialized to SDP.
1016 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
1017 // the SessionDescription, it is necessary to do that here to in order to
1018 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
1019 // https://code.google.com/p/webrtc/issues/detail?id=1356
1021 EXPECT_TRUE(answer
->ToString(&sdp
));
1022 std::unique_ptr
<SessionDescriptionInterface
> new_answer(
1023 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
1024 EXPECT_TRUE(DoSetLocalDescription(std::move(new_answer
)));
1025 EXPECT_EQ(PeerConnectionInterface::kStable
, observer_
.state_
);
1028 void CreatePrAnswerAsLocalDescription() {
1029 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1030 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
1033 EXPECT_TRUE(answer
->ToString(&sdp
));
1034 std::unique_ptr
<SessionDescriptionInterface
> pr_answer(
1035 webrtc::CreateSessionDescription(SdpType::kPrAnswer
, sdp
));
1036 EXPECT_TRUE(DoSetLocalDescription(std::move(pr_answer
)));
1037 EXPECT_EQ(PeerConnectionInterface::kHaveLocalPrAnswer
, observer_
.state_
);
1040 void CreateOfferReceiveAnswer() {
1041 CreateOfferAsLocalDescription();
1043 EXPECT_TRUE(pc_
->local_description()->ToString(&sdp
));
1044 CreateAnswerAsRemoteDescription(sdp
);
1047 void CreateOfferAsLocalDescription() {
1048 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1049 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1050 // TODO(perkj): Currently SetLocalDescription fails if any parameters in an
1051 // audio codec change, even if the parameter has nothing to do with
1052 // receiving. Not all parameters are serialized to SDP.
1053 // Since CreatePrAnswerAsLocalDescription serialize/deserialize
1054 // the SessionDescription, it is necessary to do that here to in order to
1055 // get ReceiveOfferCreatePrAnswerAndAnswer and RenegotiateAudioOnly to pass.
1056 // https://code.google.com/p/webrtc/issues/detail?id=1356
1058 EXPECT_TRUE(offer
->ToString(&sdp
));
1059 std::unique_ptr
<SessionDescriptionInterface
> new_offer(
1060 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
1062 EXPECT_TRUE(DoSetLocalDescription(std::move(new_offer
)));
1063 EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer
, observer_
.state_
);
1064 // Wait for the ice_complete message, so that SDP will have candidates.
1065 EXPECT_TRUE_WAIT(observer_
.ice_gathering_complete_
, kTimeout
);
1068 void CreateAnswerAsRemoteDescription(const std::string
& sdp
) {
1069 std::unique_ptr
<SessionDescriptionInterface
> answer(
1070 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
1071 ASSERT_TRUE(answer
);
1072 EXPECT_TRUE(DoSetRemoteDescription(std::move(answer
)));
1073 EXPECT_EQ(PeerConnectionInterface::kStable
, observer_
.state_
);
1076 void CreatePrAnswerAndAnswerAsRemoteDescription(const std::string
& sdp
) {
1077 std::unique_ptr
<SessionDescriptionInterface
> pr_answer(
1078 webrtc::CreateSessionDescription(SdpType::kPrAnswer
, sdp
));
1079 ASSERT_TRUE(pr_answer
);
1080 EXPECT_TRUE(DoSetRemoteDescription(std::move(pr_answer
)));
1081 EXPECT_EQ(PeerConnectionInterface::kHaveRemotePrAnswer
, observer_
.state_
);
1082 std::unique_ptr
<SessionDescriptionInterface
> answer(
1083 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
1084 ASSERT_TRUE(answer
);
1085 EXPECT_TRUE(DoSetRemoteDescription(std::move(answer
)));
1086 EXPECT_EQ(PeerConnectionInterface::kStable
, observer_
.state_
);
1089 // Waits until a remote stream with the given id is signaled. This helper
1090 // function will verify both OnAddTrack and OnAddStream (Plan B only) are
1091 // called with the given stream id and expected number of tracks.
1092 void WaitAndVerifyOnAddStream(const std::string
& stream_id
,
1093 int expected_num_tracks
) {
1094 // Verify that both OnAddStream and OnAddTrack are called.
1095 EXPECT_EQ_WAIT(stream_id
, observer_
.GetLastAddedStreamId(), kTimeout
);
1096 EXPECT_EQ_WAIT(expected_num_tracks
,
1097 observer_
.CountAddTrackEventsForStream(stream_id
), kTimeout
);
1100 // Creates an offer and applies it as a local session description.
1101 // Creates an answer with the same SDP an the offer but removes all lines
1102 // that start with a:ssrc"
1103 void CreateOfferReceiveAnswerWithoutSsrc() {
1104 CreateOfferAsLocalDescription();
1106 EXPECT_TRUE(pc_
->local_description()->ToString(&sdp
));
1107 SetSsrcToZero(&sdp
);
1108 CreateAnswerAsRemoteDescription(sdp
);
1111 // This function creates a MediaStream with label kStreams[0] and
1112 // `number_of_audio_tracks` and `number_of_video_tracks` tracks and the
1113 // corresponding SessionDescriptionInterface. The SessionDescriptionInterface
1114 // is returned and the MediaStream is stored in
1115 // `reference_collection_`
1116 std::unique_ptr
<SessionDescriptionInterface
>
1117 CreateSessionDescriptionAndReference(size_t number_of_audio_tracks
,
1118 size_t number_of_video_tracks
) {
1119 EXPECT_LE(number_of_audio_tracks
, 2u);
1120 EXPECT_LE(number_of_video_tracks
, 2u);
1122 reference_collection_
= StreamCollection::Create();
1123 std::string sdp_ms1
= std::string(kSdpStringInit
);
1125 std::string mediastream_id
= kStreams
[0];
1127 rtc::scoped_refptr
<webrtc::MediaStreamInterface
> stream(
1128 webrtc::MediaStream::Create(mediastream_id
));
1129 reference_collection_
->AddStream(stream
);
1131 if (number_of_audio_tracks
> 0) {
1132 sdp_ms1
+= std::string(kSdpStringAudio
);
1133 sdp_ms1
+= std::string(kSdpStringMs1Audio0
);
1134 AddAudioTrack(kAudioTracks
[0], stream
.get());
1136 if (number_of_audio_tracks
> 1) {
1137 sdp_ms1
+= kSdpStringMs1Audio1
;
1138 AddAudioTrack(kAudioTracks
[1], stream
.get());
1141 if (number_of_video_tracks
> 0) {
1142 sdp_ms1
+= std::string(kSdpStringVideo
);
1143 sdp_ms1
+= std::string(kSdpStringMs1Video0
);
1144 AddVideoTrack(kVideoTracks
[0], stream
.get());
1146 if (number_of_video_tracks
> 1) {
1147 sdp_ms1
+= kSdpStringMs1Video1
;
1148 AddVideoTrack(kVideoTracks
[1], stream
.get());
1151 return std::unique_ptr
<SessionDescriptionInterface
>(
1152 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp_ms1
));
1155 void AddAudioTrack(const std::string
& track_id
,
1156 MediaStreamInterface
* stream
) {
1157 rtc::scoped_refptr
<webrtc::AudioTrackInterface
> audio_track(
1158 webrtc::AudioTrack::Create(track_id
, nullptr));
1159 ASSERT_TRUE(stream
->AddTrack(audio_track
));
1162 void AddVideoTrack(const std::string
& track_id
,
1163 MediaStreamInterface
* stream
) {
1164 rtc::scoped_refptr
<webrtc::VideoTrackInterface
> video_track(
1165 webrtc::VideoTrack::Create(track_id
,
1166 webrtc::FakeVideoTrackSource::Create(),
1167 rtc::Thread::Current()));
1168 ASSERT_TRUE(stream
->AddTrack(video_track
));
1171 std::unique_ptr
<SessionDescriptionInterface
> CreateOfferWithOneAudioTrack() {
1172 CreatePeerConnectionWithoutDtls();
1173 AddAudioTrack(kAudioTracks
[0]);
1174 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1175 EXPECT_TRUE(DoCreateOffer(&offer
, nullptr));
1179 std::unique_ptr
<SessionDescriptionInterface
> CreateOfferWithOneAudioStream() {
1180 CreatePeerConnectionWithoutDtls();
1181 AddAudioStream(kStreamId1
);
1182 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1183 EXPECT_TRUE(DoCreateOffer(&offer
, nullptr));
1187 std::unique_ptr
<SessionDescriptionInterface
> CreateAnswerWithOneAudioTrack() {
1188 EXPECT_TRUE(DoSetRemoteDescription(CreateOfferWithOneAudioTrack()));
1189 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1190 EXPECT_TRUE(DoCreateAnswer(&answer
, nullptr));
1194 std::unique_ptr
<SessionDescriptionInterface
>
1195 CreateAnswerWithOneAudioStream() {
1196 EXPECT_TRUE(DoSetRemoteDescription(CreateOfferWithOneAudioStream()));
1197 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1198 EXPECT_TRUE(DoCreateAnswer(&answer
, nullptr));
1202 const std::string
& GetFirstAudioStreamCname(
1203 const SessionDescriptionInterface
* desc
) {
1204 const cricket::AudioContentDescription
* audio_desc
=
1205 cricket::GetFirstAudioContentDescription(desc
->description());
1206 return audio_desc
->streams()[0].cname
;
1209 std::unique_ptr
<SessionDescriptionInterface
> CreateOfferWithOptions(
1210 const RTCOfferAnswerOptions
& offer_answer_options
) {
1213 rtc::make_ref_counted
<MockCreateSessionDescriptionObserver
>();
1214 pc_
->CreateOffer(observer
.get(), offer_answer_options
);
1215 EXPECT_EQ_WAIT(true, observer
->called(), kTimeout
);
1216 return observer
->MoveDescription();
1219 void CreateOfferWithOptionsAsRemoteDescription(
1220 std::unique_ptr
<SessionDescriptionInterface
>* desc
,
1221 const RTCOfferAnswerOptions
& offer_answer_options
) {
1222 *desc
= CreateOfferWithOptions(offer_answer_options
);
1223 ASSERT_TRUE(desc
!= nullptr);
1225 EXPECT_TRUE((*desc
)->ToString(&sdp
));
1226 std::unique_ptr
<SessionDescriptionInterface
> remote_offer(
1227 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
1228 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_offer
)));
1229 EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer
, observer_
.state_
);
1232 void CreateOfferWithOptionsAsLocalDescription(
1233 std::unique_ptr
<SessionDescriptionInterface
>* desc
,
1234 const RTCOfferAnswerOptions
& offer_answer_options
) {
1235 *desc
= CreateOfferWithOptions(offer_answer_options
);
1236 ASSERT_TRUE(desc
!= nullptr);
1238 EXPECT_TRUE((*desc
)->ToString(&sdp
));
1239 std::unique_ptr
<SessionDescriptionInterface
> new_offer(
1240 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
1242 EXPECT_TRUE(DoSetLocalDescription(std::move(new_offer
)));
1243 EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer
, observer_
.state_
);
1246 bool HasCNCodecs(const cricket::ContentInfo
* content
) {
1247 RTC_DCHECK(content
);
1248 RTC_DCHECK(content
->media_description());
1249 for (const cricket::AudioCodec
& codec
:
1250 content
->media_description()->as_audio()->codecs()) {
1251 if (codec
.name
== "CN") {
1258 const char* GetSdpStringWithStream1() const {
1259 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
1260 return kSdpStringWithStream1PlanB
;
1262 return kSdpStringWithStream1UnifiedPlan
;
1266 const char* GetSdpStringWithStream1And2() const {
1267 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
1268 return kSdpStringWithStream1And2PlanB
;
1270 return kSdpStringWithStream1And2UnifiedPlan
;
1274 rtc::SocketServer
* socket_server() const { return vss_
.get(); }
1276 webrtc::test::ScopedKeyValueConfig field_trials_
;
1277 std::unique_ptr
<rtc::VirtualSocketServer
> vss_
;
1278 rtc::AutoSocketServerThread main_
;
1279 rtc::scoped_refptr
<FakeAudioCaptureModule
> fake_audio_capture_module_
;
1280 cricket::FakePortAllocator
* port_allocator_
= nullptr;
1281 FakeRTCCertificateGenerator
* fake_certificate_generator_
= nullptr;
1282 rtc::scoped_refptr
<webrtc::PeerConnectionFactoryInterface
> pc_factory_
;
1283 rtc::scoped_refptr
<PeerConnectionInterface
> pc_
;
1284 MockPeerConnectionObserver observer_
;
1285 rtc::scoped_refptr
<StreamCollection
> reference_collection_
;
1286 const SdpSemantics sdp_semantics_
;
1289 class PeerConnectionInterfaceTest
1290 : public PeerConnectionInterfaceBaseTest
,
1291 public ::testing::WithParamInterface
<SdpSemantics
> {
1293 PeerConnectionInterfaceTest() : PeerConnectionInterfaceBaseTest(GetParam()) {}
1296 class PeerConnectionInterfaceTestPlanB
1297 : public PeerConnectionInterfaceBaseTest
{
1299 PeerConnectionInterfaceTestPlanB()
1300 : PeerConnectionInterfaceBaseTest(SdpSemantics::kPlanB_DEPRECATED
) {}
1303 // Generate different CNAMEs when PeerConnections are created.
1304 // The CNAMEs are expected to be generated randomly. It is possible
1305 // that the test fails, though the possibility is very low.
1306 TEST_P(PeerConnectionInterfaceTest
, CnameGenerationInOffer
) {
1307 std::unique_ptr
<SessionDescriptionInterface
> offer1
=
1308 CreateOfferWithOneAudioTrack();
1309 std::unique_ptr
<SessionDescriptionInterface
> offer2
=
1310 CreateOfferWithOneAudioTrack();
1311 EXPECT_NE(GetFirstAudioStreamCname(offer1
.get()),
1312 GetFirstAudioStreamCname(offer2
.get()));
1315 TEST_P(PeerConnectionInterfaceTest
, CnameGenerationInAnswer
) {
1316 std::unique_ptr
<SessionDescriptionInterface
> answer1
=
1317 CreateAnswerWithOneAudioTrack();
1318 std::unique_ptr
<SessionDescriptionInterface
> answer2
=
1319 CreateAnswerWithOneAudioTrack();
1320 EXPECT_NE(GetFirstAudioStreamCname(answer1
.get()),
1321 GetFirstAudioStreamCname(answer2
.get()));
1324 TEST_P(PeerConnectionInterfaceTest
,
1325 CreatePeerConnectionWithDifferentConfigurations
) {
1326 CreatePeerConnectionWithDifferentConfigurations();
1329 TEST_P(PeerConnectionInterfaceTest
,
1330 CreatePeerConnectionWithDifferentIceTransportsTypes
) {
1331 CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kNone
);
1332 EXPECT_EQ(cricket::CF_NONE
, port_allocator_
->candidate_filter());
1333 CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kRelay
);
1334 EXPECT_EQ(cricket::CF_RELAY
, port_allocator_
->candidate_filter());
1335 CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kNoHost
);
1336 EXPECT_EQ(cricket::CF_ALL
& ~cricket::CF_HOST
,
1337 port_allocator_
->candidate_filter());
1338 CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kAll
);
1339 EXPECT_EQ(cricket::CF_ALL
, port_allocator_
->candidate_filter());
1342 // Test that when a PeerConnection is created with a nonzero candidate pool
1343 // size, the pooled PortAllocatorSession is created with all the attributes
1344 // in the RTCConfiguration.
1345 TEST_P(PeerConnectionInterfaceTest
, CreatePeerConnectionWithPooledCandidates
) {
1346 PeerConnectionInterface::RTCConfiguration config
;
1347 config
.sdp_semantics
= sdp_semantics_
;
1348 PeerConnectionInterface::IceServer server
;
1349 server
.uri
= kStunAddressOnly
;
1350 config
.servers
.push_back(server
);
1351 config
.type
= PeerConnectionInterface::kRelay
;
1352 config
.tcp_candidate_policy
=
1353 PeerConnectionInterface::kTcpCandidatePolicyDisabled
;
1354 config
.candidate_network_policy
=
1355 PeerConnectionInterface::kCandidateNetworkPolicyLowCost
;
1356 config
.ice_candidate_pool_size
= 1;
1357 CreatePeerConnection(config
);
1359 const cricket::FakePortAllocatorSession
* session
=
1360 static_cast<const cricket::FakePortAllocatorSession
*>(
1361 port_allocator_
->GetPooledSession());
1362 ASSERT_NE(nullptr, session
);
1363 EXPECT_EQ(1UL, session
->stun_servers().size());
1364 EXPECT_LT(0U, session
->flags() & cricket::PORTALLOCATOR_DISABLE_TCP
);
1366 session
->flags() & cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS
);
1369 // Test that network-related RTCConfiguration members are applied to the
1370 // PortAllocator when CreatePeerConnection is called. Specifically:
1371 // - disable_ipv6_on_wifi
1372 // - max_ipv6_networks
1373 // - tcp_candidate_policy
1374 // - candidate_network_policy
1375 // - prune_turn_ports
1377 // Note that the candidate filter (RTCConfiguration::type) is already tested
1379 TEST_P(PeerConnectionInterfaceTest
,
1380 CreatePeerConnectionAppliesNetworkConfigToPortAllocator
) {
1381 // Create fake port allocator.
1382 std::unique_ptr
<rtc::PacketSocketFactory
> packet_socket_factory(
1383 new rtc::BasicPacketSocketFactory(socket_server()));
1384 std::unique_ptr
<cricket::FakePortAllocator
> port_allocator(
1385 new cricket::FakePortAllocator(
1386 rtc::Thread::Current(), packet_socket_factory
.get(), &field_trials_
));
1387 cricket::FakePortAllocator
* raw_port_allocator
= port_allocator
.get();
1389 // Create RTCConfiguration with some network-related fields relevant to
1390 // PortAllocator populated.
1391 PeerConnectionInterface::RTCConfiguration config
;
1392 config
.sdp_semantics
= sdp_semantics_
;
1393 config
.disable_ipv6_on_wifi
= true;
1394 config
.max_ipv6_networks
= 10;
1395 config
.tcp_candidate_policy
=
1396 PeerConnectionInterface::kTcpCandidatePolicyDisabled
;
1397 config
.candidate_network_policy
=
1398 PeerConnectionInterface::kCandidateNetworkPolicyLowCost
;
1399 config
.prune_turn_ports
= true;
1401 // Create the PC factory and PC with the above config.
1402 rtc::scoped_refptr
<webrtc::PeerConnectionFactoryInterface
> pc_factory(
1403 webrtc::CreatePeerConnectionFactory(
1404 rtc::Thread::Current(), rtc::Thread::Current(),
1405 rtc::Thread::Current(), fake_audio_capture_module_
,
1406 webrtc::CreateBuiltinAudioEncoderFactory(),
1407 webrtc::CreateBuiltinAudioDecoderFactory(),
1408 std::make_unique
<webrtc::VideoEncoderFactoryTemplate
<
1409 webrtc::LibvpxVp8EncoderTemplateAdapter
,
1410 webrtc::LibvpxVp9EncoderTemplateAdapter
,
1411 webrtc::OpenH264EncoderTemplateAdapter
,
1412 webrtc::LibaomAv1EncoderTemplateAdapter
>>(),
1413 std::make_unique
<webrtc::VideoDecoderFactoryTemplate
<
1414 webrtc::LibvpxVp8DecoderTemplateAdapter
,
1415 webrtc::LibvpxVp9DecoderTemplateAdapter
,
1416 webrtc::OpenH264DecoderTemplateAdapter
,
1417 webrtc::Dav1dDecoderTemplateAdapter
>>(),
1418 nullptr /* audio_mixer */, nullptr /* audio_processing */));
1419 PeerConnectionDependencies
pc_dependencies(&observer_
);
1420 pc_dependencies
.allocator
= std::move(port_allocator
);
1421 auto result
= pc_factory_
->CreatePeerConnectionOrError(
1422 config
, std::move(pc_dependencies
));
1423 EXPECT_TRUE(result
.ok());
1424 observer_
.SetPeerConnectionInterface(result
.value().get());
1426 // Now validate that the config fields set above were applied to the
1427 // PortAllocator, as flags or otherwise.
1428 EXPECT_FALSE(raw_port_allocator
->flags() &
1429 cricket::PORTALLOCATOR_ENABLE_IPV6_ON_WIFI
);
1430 EXPECT_EQ(10, raw_port_allocator
->max_ipv6_networks());
1431 EXPECT_TRUE(raw_port_allocator
->flags() & cricket::PORTALLOCATOR_DISABLE_TCP
);
1432 EXPECT_TRUE(raw_port_allocator
->flags() &
1433 cricket::PORTALLOCATOR_DISABLE_COSTLY_NETWORKS
);
1434 EXPECT_EQ(webrtc::PRUNE_BASED_ON_PRIORITY
,
1435 raw_port_allocator
->turn_port_prune_policy());
1438 // Check that GetConfiguration returns the configuration the PeerConnection was
1439 // constructed with, before SetConfiguration is called.
1440 TEST_P(PeerConnectionInterfaceTest
, GetConfigurationAfterCreatePeerConnection
) {
1441 PeerConnectionInterface::RTCConfiguration config
;
1442 config
.sdp_semantics
= sdp_semantics_
;
1443 config
.type
= PeerConnectionInterface::kRelay
;
1444 CreatePeerConnection(config
);
1446 PeerConnectionInterface::RTCConfiguration returned_config
=
1447 pc_
->GetConfiguration();
1448 EXPECT_EQ(PeerConnectionInterface::kRelay
, returned_config
.type
);
1451 // Check that GetConfiguration returns the last configuration passed into
1452 // SetConfiguration.
1453 TEST_P(PeerConnectionInterfaceTest
, GetConfigurationAfterSetConfiguration
) {
1454 PeerConnectionInterface::RTCConfiguration starting_config
;
1455 starting_config
.sdp_semantics
= sdp_semantics_
;
1456 starting_config
.bundle_policy
=
1457 webrtc::PeerConnection::kBundlePolicyMaxBundle
;
1458 CreatePeerConnection(starting_config
);
1460 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
1461 config
.type
= PeerConnectionInterface::kRelay
;
1462 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
1464 PeerConnectionInterface::RTCConfiguration returned_config
=
1465 pc_
->GetConfiguration();
1466 EXPECT_EQ(PeerConnectionInterface::kRelay
, returned_config
.type
);
1469 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationFailsAfterClose
) {
1470 CreatePeerConnection();
1475 pc_
->SetConfiguration(PeerConnectionInterface::RTCConfiguration()).ok());
1478 TEST_F(PeerConnectionInterfaceTestPlanB
, AddStreams
) {
1479 CreatePeerConnectionWithoutDtls();
1480 AddVideoStream(kStreamId1
);
1481 AddAudioStream(kStreamId2
);
1482 ASSERT_EQ(2u, pc_
->local_streams()->count());
1484 // Test we can add multiple local streams to one peerconnection.
1485 rtc::scoped_refptr
<MediaStreamInterface
> stream(
1486 pc_factory_
->CreateLocalMediaStream(kStreamId3
));
1487 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1488 pc_factory_
->CreateAudioTrack(
1489 kStreamId3
, static_cast<AudioSourceInterface
*>(nullptr)));
1490 stream
->AddTrack(audio_track
);
1491 EXPECT_TRUE(pc_
->AddStream(stream
.get()));
1492 EXPECT_EQ(3u, pc_
->local_streams()->count());
1494 // Remove the third stream.
1495 pc_
->RemoveStream(pc_
->local_streams()->at(2));
1496 EXPECT_EQ(2u, pc_
->local_streams()->count());
1498 // Remove the second stream.
1499 pc_
->RemoveStream(pc_
->local_streams()->at(1));
1500 EXPECT_EQ(1u, pc_
->local_streams()->count());
1502 // Remove the first stream.
1503 pc_
->RemoveStream(pc_
->local_streams()->at(0));
1504 EXPECT_EQ(0u, pc_
->local_streams()->count());
1507 // Test that the created offer includes streams we added.
1508 // Don't run under Unified Plan since the stream API is not available.
1509 TEST_F(PeerConnectionInterfaceTestPlanB
, AddedStreamsPresentInOffer
) {
1510 CreatePeerConnectionWithoutDtls();
1511 AddAudioVideoStream(kStreamId1
, "audio_track", "video_track");
1512 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1513 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1515 const cricket::AudioContentDescription
* audio_desc
=
1516 cricket::GetFirstAudioContentDescription(offer
->description());
1517 EXPECT_TRUE(ContainsTrack(audio_desc
->streams(), kStreamId1
, "audio_track"));
1519 const cricket::VideoContentDescription
* video_desc
=
1520 cricket::GetFirstVideoContentDescription(offer
->description());
1521 EXPECT_TRUE(ContainsTrack(video_desc
->streams(), kStreamId1
, "video_track"));
1523 // Add another stream and ensure the offer includes both the old and new
1525 AddAudioVideoStream(kStreamId2
, "audio_track2", "video_track2");
1526 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1528 audio_desc
= cricket::GetFirstAudioContentDescription(offer
->description());
1529 EXPECT_TRUE(ContainsTrack(audio_desc
->streams(), kStreamId1
, "audio_track"));
1530 EXPECT_TRUE(ContainsTrack(audio_desc
->streams(), kStreamId2
, "audio_track2"));
1532 video_desc
= cricket::GetFirstVideoContentDescription(offer
->description());
1533 EXPECT_TRUE(ContainsTrack(video_desc
->streams(), kStreamId1
, "video_track"));
1534 EXPECT_TRUE(ContainsTrack(video_desc
->streams(), kStreamId2
, "video_track2"));
1537 // Don't run under Unified Plan since the stream API is not available.
1538 TEST_F(PeerConnectionInterfaceTestPlanB
, RemoveStream
) {
1539 CreatePeerConnectionWithoutDtls();
1540 AddVideoStream(kStreamId1
);
1541 ASSERT_EQ(1u, pc_
->local_streams()->count());
1542 pc_
->RemoveStream(pc_
->local_streams()->at(0));
1543 EXPECT_EQ(0u, pc_
->local_streams()->count());
1546 // Test for AddTrack and RemoveTrack methods.
1547 // Tests that the created offer includes tracks we added,
1548 // and that the RtpSenders are created correctly.
1549 // Also tests that RemoveTrack removes the tracks from subsequent offers.
1550 // Only tested with Plan B since Unified Plan is covered in more detail by tests
1551 // in peerconnection_jsep_unittests.cc
1552 TEST_F(PeerConnectionInterfaceTestPlanB
, AddTrackRemoveTrack
) {
1553 CreatePeerConnectionWithoutDtls();
1554 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1555 CreateAudioTrack("audio_track"));
1556 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1557 CreateVideoTrack("video_track"));
1558 auto audio_sender
= pc_
->AddTrack(audio_track
, {kStreamId1
}).MoveValue();
1559 auto video_sender
= pc_
->AddTrack(video_track
, {kStreamId1
}).MoveValue();
1560 EXPECT_EQ(1UL, audio_sender
->stream_ids().size());
1561 EXPECT_EQ(kStreamId1
, audio_sender
->stream_ids()[0]);
1562 EXPECT_EQ("audio_track", audio_sender
->id());
1563 EXPECT_EQ(audio_track
, audio_sender
->track());
1564 EXPECT_EQ(1UL, video_sender
->stream_ids().size());
1565 EXPECT_EQ(kStreamId1
, video_sender
->stream_ids()[0]);
1566 EXPECT_EQ("video_track", video_sender
->id());
1567 EXPECT_EQ(video_track
, video_sender
->track());
1569 // Now create an offer and check for the senders.
1570 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1571 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1573 const cricket::ContentInfo
* audio_content
=
1574 cricket::GetFirstAudioContent(offer
->description());
1575 EXPECT_TRUE(ContainsTrack(audio_content
->media_description()->streams(),
1576 kStreamId1
, "audio_track"));
1578 const cricket::ContentInfo
* video_content
=
1579 cricket::GetFirstVideoContent(offer
->description());
1580 EXPECT_TRUE(ContainsTrack(video_content
->media_description()->streams(),
1581 kStreamId1
, "video_track"));
1583 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
1585 // Now try removing the tracks.
1586 EXPECT_TRUE(pc_
->RemoveTrackOrError(audio_sender
).ok());
1587 EXPECT_TRUE(pc_
->RemoveTrackOrError(video_sender
).ok());
1589 // Create a new offer and ensure it doesn't contain the removed senders.
1590 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1592 audio_content
= cricket::GetFirstAudioContent(offer
->description());
1593 EXPECT_FALSE(ContainsTrack(audio_content
->media_description()->streams(),
1594 kStreamId1
, "audio_track"));
1596 video_content
= cricket::GetFirstVideoContent(offer
->description());
1597 EXPECT_FALSE(ContainsTrack(video_content
->media_description()->streams(),
1598 kStreamId1
, "video_track"));
1600 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
1602 // Calling RemoveTrack on a sender no longer attached to a PeerConnection
1603 // should return false.
1604 EXPECT_FALSE(pc_
->RemoveTrackOrError(audio_sender
).ok());
1605 EXPECT_FALSE(pc_
->RemoveTrackOrError(video_sender
).ok());
1608 // Test for AddTrack with init_send_encoding.
1609 TEST_F(PeerConnectionInterfaceTestPlanB
, AddTrackWithSendEncodings
) {
1610 CreatePeerConnectionWithoutDtls();
1611 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1612 CreateAudioTrack("audio_track"));
1613 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1614 CreateVideoTrack("video_track"));
1615 RtpEncodingParameters audio_encodings
;
1616 audio_encodings
.active
= false;
1618 pc_
->AddTrack(audio_track
, {kStreamId1
}, {audio_encodings
}).MoveValue();
1619 RtpEncodingParameters video_encodings
;
1620 video_encodings
.active
= true;
1622 pc_
->AddTrack(video_track
, {kStreamId1
}, {video_encodings
}).MoveValue();
1623 EXPECT_EQ(1UL, audio_sender
->stream_ids().size());
1624 EXPECT_EQ(kStreamId1
, audio_sender
->stream_ids()[0]);
1625 EXPECT_EQ("audio_track", audio_sender
->id());
1626 EXPECT_EQ(audio_track
, audio_sender
->track());
1627 EXPECT_EQ(1UL, video_sender
->stream_ids().size());
1628 EXPECT_EQ(kStreamId1
, video_sender
->stream_ids()[0]);
1629 EXPECT_EQ("video_track", video_sender
->id());
1630 EXPECT_EQ(video_track
, video_sender
->track());
1632 // Now create an offer and check for the senders.
1633 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1634 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1636 const cricket::ContentInfo
* audio_content
=
1637 cricket::GetFirstAudioContent(offer
->description());
1638 EXPECT_TRUE(ContainsTrack(audio_content
->media_description()->streams(),
1639 kStreamId1
, "audio_track"));
1641 const cricket::ContentInfo
* video_content
=
1642 cricket::GetFirstVideoContent(offer
->description());
1643 EXPECT_TRUE(ContainsTrack(video_content
->media_description()->streams(),
1644 kStreamId1
, "video_track"));
1646 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
1648 // Check the encodings.
1649 ASSERT_THAT(audio_sender
->GetParameters().encodings
, SizeIs(1));
1650 EXPECT_THAT(audio_sender
->GetParameters().encodings
[0].active
, Eq(false));
1651 ASSERT_THAT(video_sender
->GetParameters().encodings
, SizeIs(1));
1652 EXPECT_THAT(video_sender
->GetParameters().encodings
[0].active
, Eq(true));
1654 // Now try removing the tracks.
1655 EXPECT_TRUE(pc_
->RemoveTrackOrError(audio_sender
).ok());
1656 EXPECT_TRUE(pc_
->RemoveTrackOrError(video_sender
).ok());
1659 // Test creating senders without a stream specified,
1660 // expecting a random stream ID to be generated.
1661 TEST_P(PeerConnectionInterfaceTest
, AddTrackWithoutStream
) {
1662 CreatePeerConnectionWithoutDtls();
1663 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1664 CreateAudioTrack("audio_track"));
1665 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1666 CreateVideoTrack("video_track"));
1668 pc_
->AddTrack(audio_track
, std::vector
<std::string
>()).MoveValue();
1670 pc_
->AddTrack(video_track
, std::vector
<std::string
>()).MoveValue();
1671 EXPECT_EQ("audio_track", audio_sender
->id());
1672 EXPECT_EQ(audio_track
, audio_sender
->track());
1673 EXPECT_EQ("video_track", video_sender
->id());
1674 EXPECT_EQ(video_track
, video_sender
->track());
1675 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
1676 // If the ID is truly a random GUID, it should be infinitely unlikely they
1677 // will be the same.
1678 EXPECT_NE(video_sender
->stream_ids(), audio_sender
->stream_ids());
1680 // We allows creating tracks without stream ids under Unified Plan
1682 EXPECT_EQ(0u, video_sender
->stream_ids().size());
1683 EXPECT_EQ(0u, audio_sender
->stream_ids().size());
1687 // Test that we can call GetStats() after AddTrack but before connecting
1688 // the PeerConnection to a peer.
1689 TEST_P(PeerConnectionInterfaceTest
, AddTrackBeforeConnecting
) {
1690 CreatePeerConnectionWithoutDtls();
1691 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1692 CreateAudioTrack("audio_track"));
1693 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1694 CreateVideoTrack("video_track"));
1695 auto audio_sender
= pc_
->AddTrack(audio_track
, std::vector
<std::string
>());
1696 auto video_sender
= pc_
->AddTrack(video_track
, std::vector
<std::string
>());
1697 EXPECT_TRUE(DoGetStats(nullptr));
1700 TEST_P(PeerConnectionInterfaceTest
, AttachmentIdIsSetOnAddTrack
) {
1701 CreatePeerConnectionWithoutDtls();
1702 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
1703 CreateAudioTrack("audio_track"));
1704 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1705 CreateVideoTrack("video_track"));
1706 auto audio_sender
= pc_
->AddTrack(audio_track
, std::vector
<std::string
>());
1707 ASSERT_TRUE(audio_sender
.ok());
1708 auto* audio_sender_proxy
=
1709 static_cast<RtpSenderProxyWithInternal
<RtpSenderInternal
>*>(
1710 audio_sender
.value().get());
1711 EXPECT_NE(0, audio_sender_proxy
->internal()->AttachmentId());
1713 auto video_sender
= pc_
->AddTrack(video_track
, std::vector
<std::string
>());
1714 ASSERT_TRUE(video_sender
.ok());
1715 auto* video_sender_proxy
=
1716 static_cast<RtpSenderProxyWithInternal
<RtpSenderInternal
>*>(
1717 video_sender
.value().get());
1718 EXPECT_NE(0, video_sender_proxy
->internal()->AttachmentId());
1721 // Don't run under Unified Plan since the stream API is not available.
1722 TEST_F(PeerConnectionInterfaceTestPlanB
, AttachmentIdIsSetOnAddStream
) {
1723 CreatePeerConnectionWithoutDtls();
1724 AddVideoStream(kStreamId1
);
1725 auto senders
= pc_
->GetSenders();
1726 ASSERT_EQ(1u, senders
.size());
1727 auto* sender_proxy
=
1728 static_cast<RtpSenderProxyWithInternal
<RtpSenderInternal
>*>(
1730 EXPECT_NE(0, sender_proxy
->internal()->AttachmentId());
1733 TEST_P(PeerConnectionInterfaceTest
, CreateOfferReceiveAnswer
) {
1735 WaitAndVerifyOnAddStream(kStreamId1
, 2);
1736 VerifyRemoteRtpHeaderExtensions();
1739 TEST_P(PeerConnectionInterfaceTest
, CreateOfferReceivePrAnswerAndAnswer
) {
1740 CreatePeerConnectionWithoutDtls();
1741 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
1742 CreateOfferAsLocalDescription();
1744 EXPECT_TRUE(pc_
->local_description()->ToString(&offer
));
1745 CreatePrAnswerAndAnswerAsRemoteDescription(offer
);
1746 WaitAndVerifyOnAddStream(kStreamId1
, 1);
1749 TEST_P(PeerConnectionInterfaceTest
, ReceiveOfferCreateAnswer
) {
1750 CreatePeerConnectionWithoutDtls();
1751 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
1753 CreateOfferAsRemoteDescription();
1754 CreateAnswerAsLocalDescription();
1756 WaitAndVerifyOnAddStream(kStreamId1
, 1);
1759 TEST_P(PeerConnectionInterfaceTest
, ReceiveOfferCreatePrAnswerAndAnswer
) {
1760 CreatePeerConnectionWithoutDtls();
1761 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
1763 CreateOfferAsRemoteDescription();
1764 CreatePrAnswerAsLocalDescription();
1765 CreateAnswerAsLocalDescription();
1767 WaitAndVerifyOnAddStream(kStreamId1
, 1);
1770 // Don't run under Unified Plan since the stream API is not available.
1771 TEST_F(PeerConnectionInterfaceTestPlanB
, Renegotiate
) {
1773 ASSERT_EQ(1u, pc_
->remote_streams()->count());
1774 pc_
->RemoveStream(pc_
->local_streams()->at(0));
1775 CreateOfferReceiveAnswer();
1776 EXPECT_EQ(0u, pc_
->remote_streams()->count());
1777 AddVideoStream(kStreamId1
);
1778 CreateOfferReceiveAnswer();
1781 // Tests that after negotiating an audio only call, the respondent can perform a
1782 // renegotiation that removes the audio stream.
1783 TEST_F(PeerConnectionInterfaceTestPlanB
, RenegotiateAudioOnly
) {
1784 CreatePeerConnectionWithoutDtls();
1785 AddAudioStream(kStreamId1
);
1786 CreateOfferAsRemoteDescription();
1787 CreateAnswerAsLocalDescription();
1789 ASSERT_EQ(1u, pc_
->remote_streams()->count());
1790 pc_
->RemoveStream(pc_
->local_streams()->at(0));
1791 CreateOfferReceiveAnswer();
1792 EXPECT_EQ(0u, pc_
->remote_streams()->count());
1795 // Test that candidates are generated and that we can parse our own candidates.
1796 TEST_P(PeerConnectionInterfaceTest
, IceCandidates
) {
1797 CreatePeerConnectionWithoutDtls();
1799 EXPECT_FALSE(pc_
->AddIceCandidate(observer_
.last_candidate()));
1800 // SetRemoteDescription takes ownership of offer.
1801 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1802 AddVideoTrack(kVideoTracks
[0]);
1803 EXPECT_TRUE(DoCreateOffer(&offer
, nullptr));
1804 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
1806 // SetLocalDescription takes ownership of answer.
1807 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1808 EXPECT_TRUE(DoCreateAnswer(&answer
, nullptr));
1809 EXPECT_TRUE(DoSetLocalDescription(std::move(answer
)));
1811 EXPECT_TRUE_WAIT(observer_
.last_candidate() != nullptr, kTimeout
);
1812 EXPECT_TRUE_WAIT(observer_
.ice_gathering_complete_
, kTimeout
);
1814 EXPECT_TRUE(pc_
->AddIceCandidate(observer_
.last_candidate()));
1817 // Test that CreateOffer and CreateAnswer will fail if the track labels are
1819 TEST_F(PeerConnectionInterfaceTestPlanB
, CreateOfferAnswerWithInvalidStream
) {
1820 CreatePeerConnectionWithoutDtls();
1821 // Create a regular offer for the CreateAnswer test later.
1822 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1823 EXPECT_TRUE(DoCreateOffer(&offer
, nullptr));
1827 // Create a local stream with audio&video tracks having same label.
1828 AddAudioTrack("track_label", {kStreamId1
});
1829 AddVideoTrack("track_label", {kStreamId1
});
1832 EXPECT_FALSE(DoCreateOffer(&offer
, nullptr));
1834 // Test CreateAnswer
1835 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1836 EXPECT_FALSE(DoCreateAnswer(&answer
, nullptr));
1839 // Test that we will get different SSRCs for each tracks in the offer and answer
1841 TEST_P(PeerConnectionInterfaceTest
, SsrcInOfferAnswer
) {
1842 CreatePeerConnectionWithoutDtls();
1843 // Create a local stream with audio&video tracks having different labels.
1844 AddAudioTrack(kAudioTracks
[0], {kStreamId1
});
1845 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
1848 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1849 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1853 GetFirstSsrc(GetFirstAudioContent(offer
->description()), &audio_ssrc
));
1855 GetFirstSsrc(GetFirstVideoContent(offer
->description()), &video_ssrc
));
1856 EXPECT_NE(audio_ssrc
, video_ssrc
);
1858 // Test CreateAnswer
1859 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
1860 std::unique_ptr
<SessionDescriptionInterface
> answer
;
1861 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
1865 GetFirstSsrc(GetFirstAudioContent(answer
->description()), &audio_ssrc
));
1867 GetFirstSsrc(GetFirstVideoContent(answer
->description()), &video_ssrc
));
1868 EXPECT_NE(audio_ssrc
, video_ssrc
);
1871 // Test that it's possible to call AddTrack on a MediaStream after adding
1872 // the stream to a PeerConnection.
1873 // TODO(deadbeef): Remove this test once this behavior is no longer supported.
1874 // Don't run under Unified Plan since the stream API is not available.
1875 TEST_F(PeerConnectionInterfaceTestPlanB
, AddTrackAfterAddStream
) {
1876 CreatePeerConnectionWithoutDtls();
1877 // Create audio stream and add to PeerConnection.
1878 AddAudioStream(kStreamId1
);
1879 MediaStreamInterface
* stream
= pc_
->local_streams()->at(0);
1881 // Add video track to the audio-only stream.
1882 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
1883 CreateVideoTrack("video_label"));
1884 stream
->AddTrack(video_track
);
1886 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1887 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1889 const cricket::MediaContentDescription
* video_desc
=
1890 cricket::GetFirstVideoContentDescription(offer
->description());
1891 EXPECT_TRUE(video_desc
!= nullptr);
1894 // Test that it's possible to call RemoveTrack on a MediaStream after adding
1895 // the stream to a PeerConnection.
1896 // TODO(deadbeef): Remove this test once this behavior is no longer supported.
1897 // Don't run under Unified Plan since the stream API is not available.
1898 TEST_F(PeerConnectionInterfaceTestPlanB
, RemoveTrackAfterAddStream
) {
1899 CreatePeerConnectionWithoutDtls();
1900 // Create audio/video stream and add to PeerConnection.
1901 AddAudioVideoStream(kStreamId1
, "audio_label", "video_label");
1902 MediaStreamInterface
* stream
= pc_
->local_streams()->at(0);
1904 // Remove the video track.
1905 stream
->RemoveTrack(stream
->GetVideoTracks()[0]);
1907 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1908 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1910 const cricket::MediaContentDescription
* video_desc
=
1911 cricket::GetFirstVideoContentDescription(offer
->description());
1912 EXPECT_TRUE(video_desc
== nullptr);
1915 // Test creating a sender with a stream ID, and ensure the ID is populated
1917 // Don't run under Unified Plan since the stream API is not available.
1918 TEST_F(PeerConnectionInterfaceTestPlanB
, CreateSenderWithStream
) {
1919 CreatePeerConnectionWithoutDtls();
1920 pc_
->CreateSender("video", kStreamId1
);
1922 std::unique_ptr
<SessionDescriptionInterface
> offer
;
1923 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
1925 const cricket::MediaContentDescription
* video_desc
=
1926 cricket::GetFirstVideoContentDescription(offer
->description());
1927 ASSERT_TRUE(video_desc
!= nullptr);
1928 ASSERT_EQ(1u, video_desc
->streams().size());
1929 EXPECT_EQ(kStreamId1
, video_desc
->streams()[0].first_stream_id());
1932 // Test that we can specify a certain track that we want statistics about.
1933 TEST_P(PeerConnectionInterfaceTest
, GetStatsForSpecificTrack
) {
1935 ASSERT_LT(0u, pc_
->GetSenders().size());
1936 ASSERT_LT(0u, pc_
->GetReceivers().size());
1937 rtc::scoped_refptr
<MediaStreamTrackInterface
> remote_audio
=
1938 pc_
->GetReceivers()[0]->track();
1939 EXPECT_TRUE(DoGetStats(remote_audio
.get()));
1941 // Remove the stream. Since we are sending to our selves the local
1942 // and the remote stream is the same.
1943 pc_
->RemoveTrackOrError(pc_
->GetSenders()[0]);
1944 // Do a re-negotiation.
1945 CreateOfferReceiveAnswer();
1947 // Test that we still can get statistics for the old track. Even if it is not
1949 EXPECT_TRUE(DoGetStats(remote_audio
.get()));
1952 // Test that we can get stats on a video track.
1953 TEST_P(PeerConnectionInterfaceTest
, GetStatsForVideoTrack
) {
1955 auto video_receiver
= GetFirstReceiverOfType(cricket::MEDIA_TYPE_VIDEO
);
1956 ASSERT_TRUE(video_receiver
);
1957 EXPECT_TRUE(DoGetStats(video_receiver
->track().get()));
1960 // Test that we don't get statistics for an invalid track.
1961 TEST_P(PeerConnectionInterfaceTest
, GetStatsForInvalidTrack
) {
1963 rtc::scoped_refptr
<AudioTrackInterface
> unknown_audio_track(
1964 pc_factory_
->CreateAudioTrack("unknown track", nullptr));
1965 EXPECT_FALSE(DoGetStats(unknown_audio_track
.get()));
1968 TEST_P(PeerConnectionInterfaceTest
, GetRTCStatsBeforeAndAfterCalling
) {
1969 CreatePeerConnectionWithoutDtls();
1970 EXPECT_TRUE(DoGetRTCStats());
1971 // Clearing stats cache is needed now, but should be temporary.
1972 // https://bugs.chromium.org/p/webrtc/issues/detail?id=8693
1973 pc_
->ClearStatsCache();
1974 AddAudioTrack(kAudioTracks
[0], {kStreamId1
});
1975 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
1976 EXPECT_TRUE(DoGetRTCStats());
1977 pc_
->ClearStatsCache();
1978 CreateOfferReceiveAnswer();
1979 EXPECT_TRUE(DoGetRTCStats());
1982 // This tests that a SCTP data channel is returned using different
1983 // DataChannelInit configurations.
1984 TEST_P(PeerConnectionInterfaceTest
, CreateSctpDataChannel
) {
1985 RTCConfiguration rtc_config
;
1986 CreatePeerConnection(rtc_config
);
1988 webrtc::DataChannelInit config
;
1989 auto channel
= pc_
->CreateDataChannelOrError("1", &config
);
1990 EXPECT_TRUE(channel
.ok());
1991 EXPECT_TRUE(channel
.value()->reliable());
1992 EXPECT_TRUE(observer_
.renegotiation_needed_
);
1993 observer_
.renegotiation_needed_
= false;
1995 config
.ordered
= false;
1996 channel
= pc_
->CreateDataChannelOrError("2", &config
);
1997 EXPECT_TRUE(channel
.ok());
1998 EXPECT_TRUE(channel
.value()->reliable());
1999 EXPECT_FALSE(observer_
.renegotiation_needed_
);
2001 config
.ordered
= true;
2002 config
.maxRetransmits
= 0;
2003 channel
= pc_
->CreateDataChannelOrError("3", &config
);
2004 EXPECT_TRUE(channel
.ok());
2005 EXPECT_FALSE(channel
.value()->reliable());
2006 EXPECT_FALSE(observer_
.renegotiation_needed_
);
2008 config
.maxRetransmits
= absl::nullopt
;
2009 config
.maxRetransmitTime
= 0;
2010 channel
= pc_
->CreateDataChannelOrError("4", &config
);
2011 EXPECT_TRUE(channel
.ok());
2012 EXPECT_FALSE(channel
.value()->reliable());
2013 EXPECT_FALSE(observer_
.renegotiation_needed_
);
2016 TEST_P(PeerConnectionInterfaceTest
, CreateSctpDataChannelWhenClosed
) {
2017 RTCConfiguration rtc_config
;
2018 CreatePeerConnection(rtc_config
);
2020 webrtc::DataChannelInit config
;
2021 auto ret
= pc_
->CreateDataChannelOrError("1", &config
);
2022 ASSERT_FALSE(ret
.ok());
2023 EXPECT_EQ(ret
.error().type(), RTCErrorType::INVALID_STATE
);
2026 // For backwards compatibility, we want people who "unset" maxRetransmits
2027 // and maxRetransmitTime by setting them to -1 to get what they want.
2028 TEST_P(PeerConnectionInterfaceTest
, CreateSctpDataChannelWithMinusOne
) {
2029 RTCConfiguration rtc_config
;
2030 CreatePeerConnection(rtc_config
);
2032 webrtc::DataChannelInit config
;
2033 config
.maxRetransmitTime
= -1;
2034 config
.maxRetransmits
= -1;
2035 auto channel
= pc_
->CreateDataChannelOrError("1", &config
);
2036 EXPECT_TRUE(channel
.ok());
2039 // This tests that no data channel is returned if both maxRetransmits and
2040 // maxRetransmitTime are set for SCTP data channels.
2041 TEST_P(PeerConnectionInterfaceTest
,
2042 CreateSctpDataChannelShouldFailForInvalidConfig
) {
2043 RTCConfiguration rtc_config
;
2044 CreatePeerConnection(rtc_config
);
2046 std::string label
= "test";
2047 webrtc::DataChannelInit config
;
2048 config
.maxRetransmits
= 0;
2049 config
.maxRetransmitTime
= 0;
2051 auto channel
= pc_
->CreateDataChannelOrError(label
, &config
);
2052 EXPECT_FALSE(channel
.ok());
2055 // The test verifies that creating a SCTP data channel with an id already in use
2056 // or out of range should fail.
2057 TEST_P(PeerConnectionInterfaceTest
,
2058 CreateSctpDataChannelWithInvalidIdShouldFail
) {
2059 RTCConfiguration rtc_config
;
2060 CreatePeerConnection(rtc_config
);
2062 webrtc::DataChannelInit config
;
2065 config
.negotiated
= true;
2066 auto channel
= pc_
->CreateDataChannelOrError("1", &config
);
2067 EXPECT_TRUE(channel
.ok());
2068 EXPECT_EQ(1, channel
.value()->id());
2070 channel
= pc_
->CreateDataChannelOrError("x", &config
);
2071 EXPECT_FALSE(channel
.ok());
2073 config
.id
= cricket::kMaxSctpSid
;
2074 config
.negotiated
= true;
2075 channel
= pc_
->CreateDataChannelOrError("max", &config
);
2076 EXPECT_TRUE(channel
.ok());
2077 EXPECT_EQ(config
.id
, channel
.value()->id());
2079 config
.id
= cricket::kMaxSctpSid
+ 1;
2080 config
.negotiated
= true;
2081 channel
= pc_
->CreateDataChannelOrError("x", &config
);
2082 EXPECT_FALSE(channel
.ok());
2085 // Verifies that duplicated label is allowed for SCTP data channel.
2086 TEST_P(PeerConnectionInterfaceTest
, SctpDuplicatedLabelAllowed
) {
2087 RTCConfiguration rtc_config
;
2088 CreatePeerConnection(rtc_config
);
2090 std::string label
= "test";
2091 auto channel
= pc_
->CreateDataChannelOrError(label
, nullptr);
2092 EXPECT_TRUE(channel
.ok());
2094 auto dup_channel
= pc_
->CreateDataChannelOrError(label
, nullptr);
2095 EXPECT_TRUE(dup_channel
.ok());
2098 #ifdef WEBRTC_HAVE_SCTP
2099 // This tests that SCTP data channels can be rejected in an answer.
2100 TEST_P(PeerConnectionInterfaceTest
, TestRejectSctpDataChannelInAnswer
)
2102 TEST_P(PeerConnectionInterfaceTest
, DISABLED_TestRejectSctpDataChannelInAnswer
)
2105 RTCConfiguration rtc_config
;
2106 CreatePeerConnection(rtc_config
);
2108 auto offer_channel
= pc_
->CreateDataChannelOrError("offer_channel", NULL
);
2110 CreateOfferAsLocalDescription();
2112 // Create an answer where the m-line for data channels are rejected.
2114 EXPECT_TRUE(pc_
->local_description()->ToString(&sdp
));
2115 std::unique_ptr
<SessionDescriptionInterface
> answer(
2116 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
2117 ASSERT_TRUE(answer
);
2118 cricket::ContentInfo
* data_info
=
2119 cricket::GetFirstDataContent(answer
->description());
2120 data_info
->rejected
= true;
2122 DoSetRemoteDescription(std::move(answer
));
2123 EXPECT_EQ(DataChannelInterface::kClosed
, offer_channel
.value()->state());
2126 // Test that we can create a session description from an SDP string from
2127 // FireFox, use it as a remote session description, generate an answer and use
2128 // the answer as a local description.
2129 TEST_P(PeerConnectionInterfaceTest
, ReceiveFireFoxOffer
) {
2130 RTCConfiguration rtc_config
;
2131 CreatePeerConnection(rtc_config
);
2132 AddAudioTrack("audio_label");
2133 AddVideoTrack("video_label");
2134 std::unique_ptr
<SessionDescriptionInterface
> desc(
2135 webrtc::CreateSessionDescription(SdpType::kOffer
,
2136 webrtc::kFireFoxSdpOffer
, nullptr));
2137 EXPECT_TRUE(DoSetSessionDescription(std::move(desc
), false));
2138 CreateAnswerAsLocalDescription();
2139 ASSERT_TRUE(pc_
->local_description() != nullptr);
2140 ASSERT_TRUE(pc_
->remote_description() != nullptr);
2142 const cricket::ContentInfo
* content
=
2143 cricket::GetFirstAudioContent(pc_
->local_description()->description());
2144 ASSERT_TRUE(content
!= nullptr);
2145 EXPECT_FALSE(content
->rejected
);
2148 cricket::GetFirstVideoContent(pc_
->local_description()->description());
2149 ASSERT_TRUE(content
!= nullptr);
2150 EXPECT_FALSE(content
->rejected
);
2151 #ifdef WEBRTC_HAVE_SCTP
2153 cricket::GetFirstDataContent(pc_
->local_description()->description());
2154 ASSERT_TRUE(content
!= nullptr);
2155 EXPECT_FALSE(content
->rejected
);
2159 // Test that fallback from DTLS to SDES is not supported.
2160 // The fallback was previously supported but was removed to simplify the code
2161 // and because it's non-standard.
2162 TEST_P(PeerConnectionInterfaceTest
, DtlsSdesFallbackNotSupported
) {
2163 RTCConfiguration rtc_config
;
2164 CreatePeerConnection(rtc_config
);
2165 // Wait for fake certificate to be generated. Previously, this is what caused
2166 // the "a=crypto" lines to be rejected.
2167 AddAudioTrack("audio_label");
2168 AddVideoTrack("video_label");
2169 ASSERT_NE(nullptr, fake_certificate_generator_
);
2170 EXPECT_EQ_WAIT(1, fake_certificate_generator_
->generated_certificates(),
2172 std::unique_ptr
<SessionDescriptionInterface
> desc(
2173 webrtc::CreateSessionDescription(SdpType::kOffer
, kDtlsSdesFallbackSdp
,
2175 EXPECT_FALSE(DoSetSessionDescription(std::move(desc
), /*local=*/false));
2178 // Test that we can create an audio only offer and receive an answer with a
2179 // limited set of audio codecs and receive an updated offer with more audio
2180 // codecs, where the added codecs are not supported.
2181 TEST_P(PeerConnectionInterfaceTest
, ReceiveUpdatedAudioOfferWithBadCodecs
) {
2182 CreatePeerConnectionWithoutDtls();
2183 AddAudioTrack("audio_label");
2184 CreateOfferAsLocalDescription();
2186 const char* answer_sdp
= (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
2187 ? webrtc::kAudioSdpPlanB
2188 : webrtc::kAudioSdpUnifiedPlan
);
2189 std::unique_ptr
<SessionDescriptionInterface
> answer(
2190 webrtc::CreateSessionDescription(SdpType::kAnswer
, answer_sdp
, nullptr));
2191 EXPECT_TRUE(DoSetSessionDescription(std::move(answer
), false));
2193 const char* reoffer_sdp
=
2194 (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
2195 ? webrtc::kAudioSdpWithUnsupportedCodecsPlanB
2196 : webrtc::kAudioSdpWithUnsupportedCodecsUnifiedPlan
);
2197 std::unique_ptr
<SessionDescriptionInterface
> updated_offer(
2198 webrtc::CreateSessionDescription(SdpType::kOffer
, reoffer_sdp
, nullptr));
2199 EXPECT_TRUE(DoSetSessionDescription(std::move(updated_offer
), false));
2200 CreateAnswerAsLocalDescription();
2203 // Test that if we're receiving (but not sending) a track, subsequent offers
2204 // will have m-lines with a=recvonly.
2205 TEST_P(PeerConnectionInterfaceTest
, CreateSubsequentRecvOnlyOffer
) {
2206 RTCConfiguration rtc_config
;
2207 CreatePeerConnection(rtc_config
);
2208 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2209 CreateAnswerAsLocalDescription();
2211 // At this point we should be receiving stream 1, but not sending anything.
2212 // A new offer should be recvonly.
2213 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2214 DoCreateOffer(&offer
, nullptr);
2216 const cricket::ContentInfo
* video_content
=
2217 cricket::GetFirstVideoContent(offer
->description());
2218 ASSERT_EQ(RtpTransceiverDirection::kRecvOnly
,
2219 video_content
->media_description()->direction());
2221 const cricket::ContentInfo
* audio_content
=
2222 cricket::GetFirstAudioContent(offer
->description());
2223 ASSERT_EQ(RtpTransceiverDirection::kRecvOnly
,
2224 audio_content
->media_description()->direction());
2227 // Test that if we're receiving (but not sending) a track, and the
2228 // offerToReceiveVideo/offerToReceiveAudio constraints are explicitly set to
2229 // false, the generated m-lines will be a=inactive.
2230 TEST_P(PeerConnectionInterfaceTest
, CreateSubsequentInactiveOffer
) {
2231 RTCConfiguration rtc_config
;
2232 CreatePeerConnection(rtc_config
);
2233 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2234 CreateAnswerAsLocalDescription();
2236 // At this point we should be receiving stream 1, but not sending anything.
2237 // A new offer would be recvonly, but we'll set the "no receive" constraints
2238 // to make it inactive.
2239 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2240 RTCOfferAnswerOptions options
;
2241 options
.offer_to_receive_audio
= 0;
2242 options
.offer_to_receive_video
= 0;
2243 DoCreateOffer(&offer
, &options
);
2245 const cricket::ContentInfo
* video_content
=
2246 cricket::GetFirstVideoContent(offer
->description());
2247 ASSERT_EQ(RtpTransceiverDirection::kInactive
,
2248 video_content
->media_description()->direction());
2250 const cricket::ContentInfo
* audio_content
=
2251 cricket::GetFirstAudioContent(offer
->description());
2252 ASSERT_EQ(RtpTransceiverDirection::kInactive
,
2253 audio_content
->media_description()->direction());
2256 // Test that we can use SetConfiguration to change the ICE servers of the
2258 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationChangesIceServers
) {
2259 CreatePeerConnection();
2261 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2262 PeerConnectionInterface::IceServer server
;
2263 server
.uri
= "stun:test_hostname";
2264 config
.servers
.push_back(server
);
2265 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2267 EXPECT_EQ(1u, port_allocator_
->stun_servers().size());
2268 EXPECT_EQ("test_hostname",
2269 port_allocator_
->stun_servers().begin()->hostname());
2272 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationChangesCandidateFilter
) {
2273 CreatePeerConnection();
2274 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2275 config
.type
= PeerConnectionInterface::kRelay
;
2276 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2277 EXPECT_EQ(cricket::CF_RELAY
, port_allocator_
->candidate_filter());
2280 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationChangesPruneTurnPortsFlag
) {
2281 PeerConnectionInterface::RTCConfiguration config
;
2282 config
.prune_turn_ports
= false;
2283 CreatePeerConnection(config
);
2284 config
= pc_
->GetConfiguration();
2285 EXPECT_EQ(webrtc::NO_PRUNE
, port_allocator_
->turn_port_prune_policy());
2287 config
.prune_turn_ports
= true;
2288 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2289 EXPECT_EQ(webrtc::PRUNE_BASED_ON_PRIORITY
,
2290 port_allocator_
->turn_port_prune_policy());
2293 // Test that the ice check interval can be changed. This does not verify that
2294 // the setting makes it all the way to P2PTransportChannel, as that would
2295 // require a very complex set of mocks.
2296 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationChangesIceCheckInterval
) {
2297 PeerConnectionInterface::RTCConfiguration config
;
2298 config
.ice_check_min_interval
= absl::nullopt
;
2299 CreatePeerConnection(config
);
2300 config
= pc_
->GetConfiguration();
2301 config
.ice_check_min_interval
= 100;
2302 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2303 config
= pc_
->GetConfiguration();
2304 EXPECT_EQ(config
.ice_check_min_interval
, 100);
2307 TEST_P(PeerConnectionInterfaceTest
,
2308 SetConfigurationChangesSurfaceIceCandidatesOnIceTransportTypeChanged
) {
2309 PeerConnectionInterface::RTCConfiguration config
;
2310 config
.surface_ice_candidates_on_ice_transport_type_changed
= false;
2311 CreatePeerConnection(config
);
2312 config
= pc_
->GetConfiguration();
2313 EXPECT_FALSE(config
.surface_ice_candidates_on_ice_transport_type_changed
);
2315 config
.surface_ice_candidates_on_ice_transport_type_changed
= true;
2316 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2317 config
= pc_
->GetConfiguration();
2318 EXPECT_TRUE(config
.surface_ice_candidates_on_ice_transport_type_changed
);
2321 // Test that when SetConfiguration changes both the pool size and other
2322 // attributes, the pooled session is created with the updated attributes.
2323 TEST_P(PeerConnectionInterfaceTest
,
2324 SetConfigurationCreatesPooledSessionCorrectly
) {
2325 CreatePeerConnection();
2326 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2327 config
.ice_candidate_pool_size
= 1;
2328 PeerConnectionInterface::IceServer server
;
2329 server
.uri
= kStunAddressOnly
;
2330 config
.servers
.push_back(server
);
2331 config
.type
= PeerConnectionInterface::kRelay
;
2332 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2334 const cricket::FakePortAllocatorSession
* session
=
2335 static_cast<const cricket::FakePortAllocatorSession
*>(
2336 port_allocator_
->GetPooledSession());
2337 ASSERT_NE(nullptr, session
);
2338 EXPECT_EQ(1UL, session
->stun_servers().size());
2341 // Test that after SetLocalDescription, changing the pool size is not allowed,
2342 // and an invalid modification error is returned.
2343 TEST_P(PeerConnectionInterfaceTest
,
2344 CantChangePoolSizeAfterSetLocalDescription
) {
2345 CreatePeerConnection();
2346 // Start by setting a size of 1.
2347 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2348 config
.ice_candidate_pool_size
= 1;
2349 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2351 // Set remote offer; can still change pool size at this point.
2352 CreateOfferAsRemoteDescription();
2353 config
.ice_candidate_pool_size
= 2;
2354 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2356 // Set local answer; now it's too late.
2357 CreateAnswerAsLocalDescription();
2358 config
.ice_candidate_pool_size
= 3;
2359 RTCError error
= pc_
->SetConfiguration(config
);
2360 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION
, error
.type());
2363 // Test that after setting an answer, extra pooled sessions are discarded. The
2364 // ICE candidate pool is only intended to be used for the first offer/answer.
2365 TEST_P(PeerConnectionInterfaceTest
,
2366 ExtraPooledSessionsDiscardedAfterApplyingAnswer
) {
2367 CreatePeerConnection();
2369 // Set a larger-than-necessary size.
2370 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2371 config
.ice_candidate_pool_size
= 4;
2372 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2375 CreateOfferAsRemoteDescription();
2376 CreateAnswerAsLocalDescription();
2378 // Expect no pooled sessions to be left.
2379 const cricket::PortAllocatorSession
* session
=
2380 port_allocator_
->GetPooledSession();
2381 EXPECT_EQ(nullptr, session
);
2384 // After Close is called, pooled candidates should be discarded so as to not
2385 // waste network resources.
2386 TEST_P(PeerConnectionInterfaceTest
, PooledSessionsDiscardedAfterClose
) {
2387 CreatePeerConnection();
2389 PeerConnectionInterface::RTCConfiguration config
= pc_
->GetConfiguration();
2390 config
.ice_candidate_pool_size
= 3;
2391 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
2394 // Expect no pooled sessions to be left.
2395 const cricket::PortAllocatorSession
* session
=
2396 port_allocator_
->GetPooledSession();
2397 EXPECT_EQ(nullptr, session
);
2400 // Test that SetConfiguration returns an invalid modification error if
2401 // modifying a field in the configuration that isn't allowed to be modified.
2402 TEST_P(PeerConnectionInterfaceTest
,
2403 SetConfigurationReturnsInvalidModificationError
) {
2404 PeerConnectionInterface::RTCConfiguration config
;
2405 config
.bundle_policy
= PeerConnectionInterface::kBundlePolicyBalanced
;
2406 config
.rtcp_mux_policy
= PeerConnectionInterface::kRtcpMuxPolicyNegotiate
;
2407 config
.continual_gathering_policy
= PeerConnectionInterface::GATHER_ONCE
;
2408 CreatePeerConnection(config
);
2410 PeerConnectionInterface::RTCConfiguration modified_config
=
2411 pc_
->GetConfiguration();
2412 modified_config
.bundle_policy
=
2413 PeerConnectionInterface::kBundlePolicyMaxBundle
;
2414 RTCError error
= pc_
->SetConfiguration(modified_config
);
2415 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION
, error
.type());
2417 modified_config
= pc_
->GetConfiguration();
2418 modified_config
.rtcp_mux_policy
=
2419 PeerConnectionInterface::kRtcpMuxPolicyRequire
;
2420 error
= pc_
->SetConfiguration(modified_config
);
2421 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION
, error
.type());
2423 modified_config
= pc_
->GetConfiguration();
2424 modified_config
.continual_gathering_policy
=
2425 PeerConnectionInterface::GATHER_CONTINUALLY
;
2426 error
= pc_
->SetConfiguration(modified_config
);
2427 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION
, error
.type());
2430 // Test that SetConfiguration returns a range error if the candidate pool size
2431 // is negative or larger than allowed by the spec.
2432 TEST_P(PeerConnectionInterfaceTest
,
2433 SetConfigurationReturnsRangeErrorForBadCandidatePoolSize
) {
2434 PeerConnectionInterface::RTCConfiguration config
;
2435 CreatePeerConnection(config
);
2436 config
= pc_
->GetConfiguration();
2438 config
.ice_candidate_pool_size
= -1;
2439 RTCError error
= pc_
->SetConfiguration(config
);
2440 EXPECT_EQ(RTCErrorType::INVALID_RANGE
, error
.type());
2442 config
.ice_candidate_pool_size
= INT_MAX
;
2443 error
= pc_
->SetConfiguration(config
);
2444 EXPECT_EQ(RTCErrorType::INVALID_RANGE
, error
.type());
2447 // Test that SetConfiguration returns a syntax error if parsing an ICE server
2449 TEST_P(PeerConnectionInterfaceTest
,
2450 SetConfigurationReturnsSyntaxErrorFromBadIceUrls
) {
2451 PeerConnectionInterface::RTCConfiguration config
;
2452 CreatePeerConnection(config
);
2453 config
= pc_
->GetConfiguration();
2455 PeerConnectionInterface::IceServer bad_server
;
2456 bad_server
.uri
= "stunn:www.example.com";
2457 config
.servers
.push_back(bad_server
);
2458 RTCError error
= pc_
->SetConfiguration(config
);
2459 EXPECT_EQ(RTCErrorType::SYNTAX_ERROR
, error
.type());
2462 // Test that SetConfiguration returns an invalid parameter error if a TURN
2463 // IceServer is missing a username or password.
2464 TEST_P(PeerConnectionInterfaceTest
,
2465 SetConfigurationReturnsInvalidParameterIfCredentialsMissing
) {
2466 PeerConnectionInterface::RTCConfiguration config
;
2467 CreatePeerConnection(config
);
2468 config
= pc_
->GetConfiguration();
2470 PeerConnectionInterface::IceServer bad_server
;
2471 bad_server
.uri
= "turn:www.example.com";
2472 // Missing password.
2473 bad_server
.username
= "foo";
2474 config
.servers
.push_back(bad_server
);
2476 EXPECT_EQ(pc_
->SetConfiguration(config
).type(),
2477 RTCErrorType::INVALID_PARAMETER
);
2480 // Test that PeerConnection::Close changes the states to closed and all remote
2481 // tracks change state to ended.
2482 TEST_P(PeerConnectionInterfaceTest
, CloseAndTestStreamsAndStates
) {
2483 // Initialize a PeerConnection and negotiate local and remote session
2487 // With Plan B, verify the stream count. The analog with Unified Plan is the
2488 // RtpTransceiver count.
2489 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
2490 ASSERT_EQ(1u, pc_
->local_streams()->count());
2491 ASSERT_EQ(1u, pc_
->remote_streams()->count());
2493 ASSERT_EQ(2u, pc_
->GetTransceivers().size());
2498 EXPECT_EQ(PeerConnectionInterface::kClosed
, pc_
->signaling_state());
2499 EXPECT_EQ(PeerConnectionInterface::kIceConnectionClosed
,
2500 pc_
->ice_connection_state());
2501 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete
,
2502 pc_
->ice_gathering_state());
2504 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
2505 EXPECT_EQ(1u, pc_
->local_streams()->count());
2506 EXPECT_EQ(1u, pc_
->remote_streams()->count());
2508 // Verify that the RtpTransceivers are still returned.
2509 EXPECT_EQ(2u, pc_
->GetTransceivers().size());
2512 auto audio_receiver
= GetFirstReceiverOfType(cricket::MEDIA_TYPE_AUDIO
);
2513 auto video_receiver
= GetFirstReceiverOfType(cricket::MEDIA_TYPE_VIDEO
);
2514 if (sdp_semantics_
== SdpSemantics::kPlanB_DEPRECATED
) {
2515 ASSERT_TRUE(audio_receiver
);
2516 ASSERT_TRUE(video_receiver
);
2517 // Track state may be updated asynchronously.
2518 EXPECT_EQ_WAIT(MediaStreamTrackInterface::kEnded
,
2519 audio_receiver
->track()->state(), kTimeout
);
2520 EXPECT_EQ_WAIT(MediaStreamTrackInterface::kEnded
,
2521 video_receiver
->track()->state(), kTimeout
);
2523 ASSERT_FALSE(audio_receiver
);
2524 ASSERT_FALSE(video_receiver
);
2528 // Test that PeerConnection methods fails gracefully after
2529 // PeerConnection::Close has been called.
2530 // Don't run under Unified Plan since the stream API is not available.
2531 TEST_F(PeerConnectionInterfaceTestPlanB
, CloseAndTestMethods
) {
2532 CreatePeerConnectionWithoutDtls();
2533 AddAudioVideoStream(kStreamId1
, "audio_label", "video_label");
2534 CreateOfferAsRemoteDescription();
2535 CreateAnswerAsLocalDescription();
2537 ASSERT_EQ(1u, pc_
->local_streams()->count());
2538 rtc::scoped_refptr
<MediaStreamInterface
> local_stream(
2539 pc_
->local_streams()->at(0));
2543 pc_
->RemoveStream(local_stream
.get());
2544 EXPECT_FALSE(pc_
->AddStream(local_stream
.get()));
2546 EXPECT_FALSE(pc_
->CreateDataChannelOrError("test", NULL
).ok());
2548 EXPECT_TRUE(pc_
->local_description() != nullptr);
2549 EXPECT_TRUE(pc_
->remote_description() != nullptr);
2551 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2552 EXPECT_FALSE(DoCreateOffer(&offer
, nullptr));
2553 std::unique_ptr
<SessionDescriptionInterface
> answer
;
2554 EXPECT_FALSE(DoCreateAnswer(&answer
, nullptr));
2557 ASSERT_TRUE(pc_
->remote_description()->ToString(&sdp
));
2558 std::unique_ptr
<SessionDescriptionInterface
> remote_offer(
2559 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
2560 EXPECT_FALSE(DoSetRemoteDescription(std::move(remote_offer
)));
2562 ASSERT_TRUE(pc_
->local_description()->ToString(&sdp
));
2563 std::unique_ptr
<SessionDescriptionInterface
> local_offer(
2564 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
2565 EXPECT_FALSE(DoSetLocalDescription(std::move(local_offer
)));
2568 // Test that GetStats can still be called after PeerConnection::Close.
2569 TEST_P(PeerConnectionInterfaceTest
, CloseAndGetStats
) {
2572 DoGetStats(nullptr);
2575 // NOTE: The series of tests below come from what used to be
2576 // mediastreamsignaling_unittest.cc, and are mostly aimed at testing that
2577 // setting a remote or local description has the expected effects.
2579 // This test verifies that the remote MediaStreams corresponding to a received
2580 // SDP string is created. In this test the two separate MediaStreams are
2582 TEST_P(PeerConnectionInterfaceTest
, UpdateRemoteStreams
) {
2583 RTCConfiguration config
;
2584 CreatePeerConnection(config
);
2585 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2587 rtc::scoped_refptr
<StreamCollection
> reference(CreateStreamCollection(1, 1));
2589 CompareStreamCollections(observer_
.remote_streams(), reference
.get()));
2590 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2591 EXPECT_TRUE(remote_stream
->GetVideoTracks()[0]->GetSource() != nullptr);
2593 // Create a session description based on another SDP with another
2595 CreateAndSetRemoteOffer(GetSdpStringWithStream1And2());
2597 rtc::scoped_refptr
<StreamCollection
> reference2(CreateStreamCollection(2, 1));
2599 CompareStreamCollections(observer_
.remote_streams(), reference2
.get()));
2602 // This test verifies that when remote tracks are added/removed from SDP, the
2603 // created remote streams are updated appropriately.
2604 // Don't run under Unified Plan since this test uses Plan B SDP to test Plan B
2605 // specific behavior.
2606 TEST_F(PeerConnectionInterfaceTestPlanB
,
2607 AddRemoveTrackFromExistingRemoteMediaStream
) {
2608 RTCConfiguration config
;
2609 CreatePeerConnection(config
);
2610 std::unique_ptr
<SessionDescriptionInterface
> desc_ms1
=
2611 CreateSessionDescriptionAndReference(1, 1);
2612 EXPECT_TRUE(DoSetRemoteDescription(std::move(desc_ms1
)));
2613 EXPECT_TRUE(CompareStreamCollections(observer_
.remote_streams(),
2614 reference_collection_
.get()));
2616 // Add extra audio and video tracks to the same MediaStream.
2617 std::unique_ptr
<SessionDescriptionInterface
> desc_ms1_two_tracks
=
2618 CreateSessionDescriptionAndReference(2, 2);
2619 EXPECT_TRUE(DoSetRemoteDescription(std::move(desc_ms1_two_tracks
)));
2620 EXPECT_TRUE(CompareStreamCollections(observer_
.remote_streams(),
2621 reference_collection_
.get()));
2622 rtc::scoped_refptr
<AudioTrackInterface
> audio_track2
=
2623 observer_
.remote_streams()->at(0)->GetAudioTracks()[1];
2624 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive
, audio_track2
->state());
2625 rtc::scoped_refptr
<VideoTrackInterface
> video_track2
=
2626 observer_
.remote_streams()->at(0)->GetVideoTracks()[1];
2627 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive
, video_track2
->state());
2629 // Remove the extra audio and video tracks.
2630 std::unique_ptr
<SessionDescriptionInterface
> desc_ms2
=
2631 CreateSessionDescriptionAndReference(1, 1);
2632 MockTrackObserver
audio_track_observer(audio_track2
.get());
2633 MockTrackObserver
video_track_observer(video_track2
.get());
2635 EXPECT_CALL(audio_track_observer
, OnChanged()).Times(Exactly(1));
2636 EXPECT_CALL(video_track_observer
, OnChanged()).Times(Exactly(1));
2637 EXPECT_TRUE(DoSetRemoteDescription(std::move(desc_ms2
)));
2638 EXPECT_TRUE(CompareStreamCollections(observer_
.remote_streams(),
2639 reference_collection_
.get()));
2640 // Track state may be updated asynchronously.
2641 EXPECT_EQ_WAIT(webrtc::MediaStreamTrackInterface::kEnded
,
2642 audio_track2
->state(), kTimeout
);
2643 EXPECT_EQ_WAIT(webrtc::MediaStreamTrackInterface::kEnded
,
2644 video_track2
->state(), kTimeout
);
2647 // This tests that remote tracks are ended if a local session description is set
2648 // that rejects the media content type.
2649 TEST_P(PeerConnectionInterfaceTest
, RejectMediaContent
) {
2650 RTCConfiguration config
;
2651 CreatePeerConnection(config
);
2652 // First create and set a remote offer, then reject its video content in our
2654 CreateAndSetRemoteOffer(kSdpStringWithStream1PlanB
);
2655 auto audio_receiver
= GetFirstReceiverOfType(cricket::MEDIA_TYPE_AUDIO
);
2656 ASSERT_TRUE(audio_receiver
);
2657 auto video_receiver
= GetFirstReceiverOfType(cricket::MEDIA_TYPE_VIDEO
);
2658 ASSERT_TRUE(video_receiver
);
2660 rtc::scoped_refptr
<MediaStreamTrackInterface
> remote_audio
=
2661 audio_receiver
->track();
2662 EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive
, remote_audio
->state());
2663 rtc::scoped_refptr
<MediaStreamTrackInterface
> remote_video
=
2664 video_receiver
->track();
2665 EXPECT_EQ(MediaStreamTrackInterface::kLive
, remote_video
->state());
2667 std::unique_ptr
<SessionDescriptionInterface
> local_answer
;
2668 EXPECT_TRUE(DoCreateAnswer(&local_answer
, nullptr));
2669 cricket::ContentInfo
* video_info
=
2670 local_answer
->description()->GetContentByName("video");
2671 video_info
->rejected
= true;
2672 EXPECT_TRUE(DoSetLocalDescription(std::move(local_answer
)));
2673 EXPECT_EQ(MediaStreamTrackInterface::kEnded
, remote_video
->state());
2674 EXPECT_EQ(MediaStreamTrackInterface::kLive
, remote_audio
->state());
2676 // Now create an offer where we reject both video and audio.
2677 std::unique_ptr
<SessionDescriptionInterface
> local_offer
;
2678 EXPECT_TRUE(DoCreateOffer(&local_offer
, nullptr));
2679 video_info
= local_offer
->description()->GetContentByName("video");
2680 ASSERT_TRUE(video_info
!= nullptr);
2681 video_info
->rejected
= true;
2682 cricket::ContentInfo
* audio_info
=
2683 local_offer
->description()->GetContentByName("audio");
2684 ASSERT_TRUE(audio_info
!= nullptr);
2685 audio_info
->rejected
= true;
2686 EXPECT_TRUE(DoSetLocalDescription(std::move(local_offer
)));
2687 // Track state may be updated asynchronously.
2688 EXPECT_EQ_WAIT(MediaStreamTrackInterface::kEnded
, remote_audio
->state(),
2690 EXPECT_EQ_WAIT(MediaStreamTrackInterface::kEnded
, remote_video
->state(),
2694 // This tests that we won't crash if the remote track has been removed outside
2695 // of PeerConnection and then PeerConnection tries to reject the track.
2696 // Don't run under Unified Plan since the stream API is not available.
2697 TEST_F(PeerConnectionInterfaceTestPlanB
, RemoveTrackThenRejectMediaContent
) {
2698 RTCConfiguration config
;
2699 CreatePeerConnection(config
);
2700 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2701 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2702 remote_stream
->RemoveTrack(remote_stream
->GetVideoTracks()[0]);
2703 remote_stream
->RemoveTrack(remote_stream
->GetAudioTracks()[0]);
2705 std::unique_ptr
<SessionDescriptionInterface
> local_answer(
2706 webrtc::CreateSessionDescription(SdpType::kAnswer
,
2707 GetSdpStringWithStream1(), nullptr));
2708 cricket::ContentInfo
* video_info
=
2709 local_answer
->description()->GetContentByName("video");
2710 video_info
->rejected
= true;
2711 cricket::ContentInfo
* audio_info
=
2712 local_answer
->description()->GetContentByName("audio");
2713 audio_info
->rejected
= true;
2714 EXPECT_TRUE(DoSetLocalDescription(std::move(local_answer
)));
2716 // No crash is a pass.
2719 // This tests that if a recvonly remote description is set, no remote streams
2720 // will be created, even if the description contains SSRCs/MSIDs.
2721 // See: https://code.google.com/p/webrtc/issues/detail?id=5054
2722 TEST_P(PeerConnectionInterfaceTest
, RecvonlyDescriptionDoesntCreateStream
) {
2723 RTCConfiguration config
;
2724 CreatePeerConnection(config
);
2726 std::string recvonly_offer
= GetSdpStringWithStream1();
2727 absl::StrReplaceAll({{kSendrecv
, kRecvonly
}}, &recvonly_offer
);
2728 CreateAndSetRemoteOffer(recvonly_offer
);
2730 EXPECT_EQ(0u, observer_
.remote_streams()->count());
2733 // This tests that a default MediaStream is created if a remote session
2734 // description doesn't contain any streams and no MSID support.
2735 // It also tests that the default stream is updated if a video m-line is added
2736 // in a subsequent session description.
2737 // Don't run under Unified Plan since this behavior is Plan B specific.
2738 TEST_F(PeerConnectionInterfaceTestPlanB
, SdpWithoutMsidCreatesDefaultStream
) {
2739 RTCConfiguration config
;
2740 CreatePeerConnection(config
);
2741 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly
);
2743 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2744 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2746 EXPECT_EQ(1u, remote_stream
->GetAudioTracks().size());
2747 EXPECT_EQ(0u, remote_stream
->GetVideoTracks().size());
2748 EXPECT_EQ("default", remote_stream
->id());
2750 CreateAndSetRemoteOffer(kSdpStringWithoutStreams
);
2751 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2752 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2753 EXPECT_EQ("defaulta0", remote_stream
->GetAudioTracks()[0]->id());
2754 EXPECT_EQ(MediaStreamTrackInterface::kLive
,
2755 remote_stream
->GetAudioTracks()[0]->state());
2756 ASSERT_EQ(1u, remote_stream
->GetVideoTracks().size());
2757 EXPECT_EQ("defaultv0", remote_stream
->GetVideoTracks()[0]->id());
2758 EXPECT_EQ(MediaStreamTrackInterface::kLive
,
2759 remote_stream
->GetVideoTracks()[0]->state());
2762 // This tests that a default MediaStream is created if a remote session
2763 // description doesn't contain any streams and media direction is send only.
2764 // Don't run under Unified Plan since this behavior is Plan B specific.
2765 TEST_F(PeerConnectionInterfaceTestPlanB
,
2766 SendOnlySdpWithoutMsidCreatesDefaultStream
) {
2767 RTCConfiguration config
;
2768 CreatePeerConnection(config
);
2769 CreateAndSetRemoteOffer(kSdpStringSendOnlyWithoutStreams
);
2771 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2772 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2774 EXPECT_EQ(1u, remote_stream
->GetAudioTracks().size());
2775 EXPECT_EQ(1u, remote_stream
->GetVideoTracks().size());
2776 EXPECT_EQ("default", remote_stream
->id());
2779 // This tests that it won't crash when PeerConnection tries to remove
2780 // a remote track that as already been removed from the MediaStream.
2781 // Don't run under Unified Plan since this behavior is Plan B specific.
2782 TEST_F(PeerConnectionInterfaceTestPlanB
, RemoveAlreadyGoneRemoteStream
) {
2783 RTCConfiguration config
;
2784 CreatePeerConnection(config
);
2785 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2786 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2787 remote_stream
->RemoveTrack(remote_stream
->GetAudioTracks()[0]);
2788 remote_stream
->RemoveTrack(remote_stream
->GetVideoTracks()[0]);
2790 CreateAndSetRemoteOffer(kSdpStringWithoutStreams
);
2792 // No crash is a pass.
2795 // This tests that a default MediaStream is created if the remote session
2796 // description doesn't contain any streams and don't contain an indication if
2797 // MSID is supported.
2798 // Don't run under Unified Plan since this behavior is Plan B specific.
2799 TEST_F(PeerConnectionInterfaceTestPlanB
,
2800 SdpWithoutMsidAndStreamsCreatesDefaultStream
) {
2801 RTCConfiguration config
;
2802 CreatePeerConnection(config
);
2803 CreateAndSetRemoteOffer(kSdpStringWithoutStreams
);
2805 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2806 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2807 EXPECT_EQ(1u, remote_stream
->GetAudioTracks().size());
2808 EXPECT_EQ(1u, remote_stream
->GetVideoTracks().size());
2811 // This tests that a default MediaStream is not created if the remote session
2812 // description doesn't contain any streams but does support MSID.
2813 // Don't run under Unified Plan since this behavior is Plan B specific.
2814 TEST_F(PeerConnectionInterfaceTestPlanB
, SdpWithMsidDontCreatesDefaultStream
) {
2815 RTCConfiguration config
;
2816 CreatePeerConnection(config
);
2817 CreateAndSetRemoteOffer(kSdpStringWithMsidWithoutStreams
);
2818 EXPECT_EQ(0u, observer_
.remote_streams()->count());
2821 // This tests that when setting a new description, the old default tracks are
2822 // not destroyed and recreated.
2823 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5250
2824 // Don't run under Unified Plan since this behavior is Plan B specific.
2825 TEST_F(PeerConnectionInterfaceTestPlanB
,
2826 DefaultTracksNotDestroyedAndRecreated
) {
2827 RTCConfiguration config
;
2828 CreatePeerConnection(config
);
2829 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly
);
2831 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2832 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2833 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2835 // Set the track to "disabled", then set a new description and ensure the
2836 // track is still disabled, which ensures it hasn't been recreated.
2837 remote_stream
->GetAudioTracks()[0]->set_enabled(false);
2838 CreateAndSetRemoteOffer(kSdpStringWithoutStreamsAudioOnly
);
2839 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2840 EXPECT_FALSE(remote_stream
->GetAudioTracks()[0]->enabled());
2843 // This tests that a default MediaStream is not created if a remote session
2844 // description is updated to not have any MediaStreams.
2845 // Don't run under Unified Plan since this behavior is Plan B specific.
2846 TEST_F(PeerConnectionInterfaceTestPlanB
, VerifyDefaultStreamIsNotCreated
) {
2847 RTCConfiguration config
;
2848 CreatePeerConnection(config
);
2849 CreateAndSetRemoteOffer(GetSdpStringWithStream1());
2850 rtc::scoped_refptr
<StreamCollection
> reference(CreateStreamCollection(1, 1));
2852 CompareStreamCollections(observer_
.remote_streams(), reference
.get()));
2854 CreateAndSetRemoteOffer(kSdpStringWithoutStreams
);
2855 EXPECT_EQ(0u, observer_
.remote_streams()->count());
2858 // This tests that a default MediaStream is created if a remote SDP comes from
2859 // an endpoint that doesn't signal SSRCs, but signals media stream IDs.
2860 TEST_F(PeerConnectionInterfaceTestPlanB
,
2861 SdpWithMsidWithoutSsrcCreatesDefaultStream
) {
2862 RTCConfiguration config
;
2863 CreatePeerConnection(config
);
2864 std::string sdp_string
= kSdpStringWithoutStreamsAudioOnly
;
2865 // Add a=msid lines to simulate a Unified Plan endpoint that only
2866 // signals stream IDs with a=msid lines.
2867 sdp_string
.append("a=msid:audio_stream_id audio_track_id\n");
2869 CreateAndSetRemoteOffer(sdp_string
);
2871 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2872 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2873 EXPECT_EQ("default", remote_stream
->id());
2874 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2877 // This tests that when a Plan B endpoint receives an SDP that signals no media
2878 // stream IDs indicated by the special character "-" in the a=msid line, that
2879 // a default stream ID will be used for the MediaStream ID. This can occur
2880 // when a Unified Plan endpoint signals no media stream IDs, but signals both
2881 // a=ssrc msid and a=msid lines for interop signaling with Plan B.
2882 TEST_F(PeerConnectionInterfaceTestPlanB
,
2883 SdpWithEmptyMsidAndSsrcCreatesDefaultStreamId
) {
2884 RTCConfiguration config
;
2885 CreatePeerConnection(config
);
2886 // Add a a=msid line to the SDP. This is prioritized when parsing the SDP, so
2887 // the sender's stream ID will be interpreted as no stream IDs.
2888 std::string sdp_string
= kSdpStringWithStream1AudioTrackOnly
;
2889 sdp_string
.append("a=msid:- audiotrack0\n");
2891 CreateAndSetRemoteOffer(sdp_string
);
2893 ASSERT_EQ(1u, observer_
.remote_streams()->count());
2894 // Because SSRCs are signaled the track ID will be what was signaled in the
2896 EXPECT_EQ("audiotrack0", observer_
.last_added_track_label_
);
2897 MediaStreamInterface
* remote_stream
= observer_
.remote_streams()->at(0);
2898 EXPECT_EQ("default", remote_stream
->id());
2899 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2901 // Previously a bug ocurred when setting the remote description a second time.
2902 // This is because we checked equality of the remote StreamParams stream ID
2903 // (empty), and the previously set stream ID for the remote sender
2904 // ("default"). This cause a track to be removed, then added, when really
2905 // nothing should occur because it is the same track.
2906 CreateAndSetRemoteOffer(sdp_string
);
2907 EXPECT_EQ(0u, observer_
.remove_track_events_
.size());
2908 EXPECT_EQ(1u, observer_
.add_track_events_
.size());
2909 EXPECT_EQ("audiotrack0", observer_
.last_added_track_label_
);
2910 remote_stream
= observer_
.remote_streams()->at(0);
2911 EXPECT_EQ("default", remote_stream
->id());
2912 ASSERT_EQ(1u, remote_stream
->GetAudioTracks().size());
2915 // This tests that an RtpSender is created when the local description is set
2916 // after adding a local stream.
2917 // TODO(deadbeef): This test and the one below it need to be updated when
2918 // an RtpSender's lifetime isn't determined by when a local description is set.
2919 // Don't run under Unified Plan since this behavior is Plan B specific.
2920 TEST_F(PeerConnectionInterfaceTestPlanB
, LocalDescriptionChanged
) {
2921 RTCConfiguration config
;
2922 CreatePeerConnection(config
);
2924 // Create an offer with 1 stream with 2 tracks of each type.
2925 rtc::scoped_refptr
<StreamCollection
> stream_collection
=
2926 CreateStreamCollection(1, 2);
2927 pc_
->AddStream(stream_collection
->at(0));
2928 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2929 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
2930 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
2932 auto senders
= pc_
->GetSenders();
2933 EXPECT_EQ(4u, senders
.size());
2934 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0]));
2935 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0]));
2936 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[1]));
2937 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[1]));
2939 // Remove an audio and video track.
2940 pc_
->RemoveStream(stream_collection
->at(0));
2941 stream_collection
= CreateStreamCollection(1, 1);
2942 pc_
->AddStream(stream_collection
->at(0));
2943 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
2944 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
2946 senders
= pc_
->GetSenders();
2947 EXPECT_EQ(2u, senders
.size());
2948 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0]));
2949 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0]));
2950 EXPECT_FALSE(ContainsSender(senders
, kAudioTracks
[1]));
2951 EXPECT_FALSE(ContainsSender(senders
, kVideoTracks
[1]));
2954 // This tests that an RtpSender is created when the local description is set
2955 // before adding a local stream.
2956 // Don't run under Unified Plan since this behavior is Plan B specific.
2957 TEST_F(PeerConnectionInterfaceTestPlanB
,
2958 AddLocalStreamAfterLocalDescriptionChanged
) {
2959 RTCConfiguration config
;
2960 CreatePeerConnection(config
);
2962 rtc::scoped_refptr
<StreamCollection
> stream_collection
=
2963 CreateStreamCollection(1, 2);
2964 // Add a stream to create the offer, but remove it afterwards.
2965 pc_
->AddStream(stream_collection
->at(0));
2966 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2967 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
2968 pc_
->RemoveStream(stream_collection
->at(0));
2970 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
2971 auto senders
= pc_
->GetSenders();
2972 EXPECT_EQ(0u, senders
.size());
2974 pc_
->AddStream(stream_collection
->at(0));
2975 senders
= pc_
->GetSenders();
2976 EXPECT_EQ(4u, senders
.size());
2977 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0]));
2978 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0]));
2979 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[1]));
2980 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[1]));
2983 // This tests that the expected behavior occurs if the SSRC on a local track is
2984 // changed when SetLocalDescription is called.
2985 TEST_P(PeerConnectionInterfaceTest
,
2986 ChangeSsrcOnTrackInLocalSessionDescription
) {
2987 RTCConfiguration config
;
2988 CreatePeerConnection(config
);
2990 AddAudioTrack(kAudioTracks
[0]);
2991 AddVideoTrack(kVideoTracks
[0]);
2992 std::unique_ptr
<SessionDescriptionInterface
> offer
;
2993 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
2994 // Grab a copy of the offer before it gets passed into the PC.
2995 std::unique_ptr
<SessionDescriptionInterface
> modified_offer
=
2996 webrtc::CreateSessionDescription(
2997 webrtc::SdpType::kOffer
, offer
->session_id(),
2998 offer
->session_version(), offer
->description()->Clone());
2999 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
3001 auto senders
= pc_
->GetSenders();
3002 EXPECT_EQ(2u, senders
.size());
3003 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0]));
3004 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0]));
3006 // Change the ssrc of the audio and video track.
3007 cricket::MediaContentDescription
* desc
=
3008 cricket::GetFirstAudioContentDescription(modified_offer
->description());
3009 ASSERT_TRUE(desc
!= nullptr);
3010 for (StreamParams
& stream
: desc
->mutable_streams()) {
3011 for (unsigned int& ssrc
: stream
.ssrcs
) {
3017 cricket::GetFirstVideoContentDescription(modified_offer
->description());
3018 ASSERT_TRUE(desc
!= nullptr);
3019 for (StreamParams
& stream
: desc
->mutable_streams()) {
3020 for (unsigned int& ssrc
: stream
.ssrcs
) {
3025 EXPECT_TRUE(DoSetLocalDescription(std::move(modified_offer
)));
3026 senders
= pc_
->GetSenders();
3027 EXPECT_EQ(2u, senders
.size());
3028 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0]));
3029 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0]));
3030 // TODO(deadbeef): Once RtpSenders expose parameters, check that the SSRC
3034 // This tests that the expected behavior occurs if a new session description is
3035 // set with the same tracks, but on a different MediaStream.
3036 // Don't run under Unified Plan since the stream API is not available.
3037 TEST_F(PeerConnectionInterfaceTestPlanB
,
3038 SignalSameTracksInSeparateMediaStream
) {
3039 RTCConfiguration config
;
3040 CreatePeerConnection(config
);
3042 rtc::scoped_refptr
<StreamCollection
> stream_collection
=
3043 CreateStreamCollection(2, 1);
3044 pc_
->AddStream(stream_collection
->at(0));
3045 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3046 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3047 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
3049 auto senders
= pc_
->GetSenders();
3050 EXPECT_EQ(2u, senders
.size());
3051 EXPECT_TRUE(ContainsSender(senders
, kAudioTracks
[0], kStreams
[0]));
3052 EXPECT_TRUE(ContainsSender(senders
, kVideoTracks
[0], kStreams
[0]));
3054 // Add a new MediaStream but with the same tracks as in the first stream.
3055 rtc::scoped_refptr
<webrtc::MediaStreamInterface
> stream_1(
3056 webrtc::MediaStream::Create(kStreams
[1]));
3057 stream_1
->AddTrack(stream_collection
->at(0)->GetVideoTracks()[0]);
3058 stream_1
->AddTrack(stream_collection
->at(0)->GetAudioTracks()[0]);
3059 pc_
->AddStream(stream_1
.get());
3061 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3062 EXPECT_TRUE(DoSetLocalDescription(std::move(offer
)));
3064 auto new_senders
= pc_
->GetSenders();
3065 // Should be the same senders as before, but with updated stream id.
3066 // Note that this behavior is subject to change in the future.
3067 // We may decide the PC should ignore existing tracks in AddStream.
3068 EXPECT_EQ(senders
, new_senders
);
3069 EXPECT_TRUE(ContainsSender(new_senders
, kAudioTracks
[0], kStreams
[1]));
3070 EXPECT_TRUE(ContainsSender(new_senders
, kVideoTracks
[0], kStreams
[1]));
3073 // This tests that PeerConnectionObserver::OnAddTrack is correctly called.
3074 TEST_P(PeerConnectionInterfaceTest
, OnAddTrackCallback
) {
3075 RTCConfiguration config
;
3076 CreatePeerConnection(config
);
3077 CreateAndSetRemoteOffer(kSdpStringWithStream1AudioTrackOnly
);
3078 EXPECT_EQ(observer_
.num_added_tracks_
, 1);
3079 EXPECT_EQ(observer_
.last_added_track_label_
, kAudioTracks
[0]);
3081 // Create and set the updated remote SDP.
3082 CreateAndSetRemoteOffer(kSdpStringWithStream1PlanB
);
3083 EXPECT_EQ(observer_
.num_added_tracks_
, 2);
3084 EXPECT_EQ(observer_
.last_added_track_label_
, kVideoTracks
[0]);
3087 // Test that when SetConfiguration is called and the configuration is
3088 // changing, the next offer causes an ICE restart.
3089 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationCausingIceRestart
) {
3090 PeerConnectionInterface::RTCConfiguration config
;
3091 config
.sdp_semantics
= sdp_semantics_
;
3092 config
.type
= PeerConnectionInterface::kRelay
;
3093 CreatePeerConnection(config
);
3094 config
= pc_
->GetConfiguration();
3095 AddAudioTrack(kAudioTracks
[0], {kStreamId1
});
3096 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
3098 // Do initial offer/answer so there's something to restart.
3099 CreateOfferAsLocalDescription();
3100 CreateAnswerAsRemoteDescription(GetSdpStringWithStream1());
3103 std::vector
<std::string
> initial_ufrags
= GetUfrags(pc_
->local_description());
3105 // Change ICE policy, which should trigger an ICE restart on the next offer.
3106 config
.type
= PeerConnectionInterface::kAll
;
3107 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
3108 CreateOfferAsLocalDescription();
3110 // Grab the new ufrags.
3111 std::vector
<std::string
> subsequent_ufrags
=
3112 GetUfrags(pc_
->local_description());
3115 EXPECT_EQ(initial_ufrags
.size(), subsequent_ufrags
.size());
3116 // Check that each ufrag is different.
3117 for (int i
= 0; i
< static_cast<int>(initial_ufrags
.size()); ++i
) {
3118 EXPECT_NE(initial_ufrags
[i
], subsequent_ufrags
[i
]);
3122 // Test that when SetConfiguration is called and the configuration *isn't*
3123 // changing, the next offer does *not* cause an ICE restart.
3124 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationNotCausingIceRestart
) {
3125 PeerConnectionInterface::RTCConfiguration config
;
3126 config
.sdp_semantics
= sdp_semantics_
;
3127 config
.type
= PeerConnectionInterface::kRelay
;
3128 CreatePeerConnection(config
);
3129 config
= pc_
->GetConfiguration();
3130 AddAudioTrack(kAudioTracks
[0]);
3131 AddVideoTrack(kVideoTracks
[0]);
3133 // Do initial offer/answer so there's something to restart.
3134 CreateOfferAsLocalDescription();
3135 CreateAnswerAsRemoteDescription(GetSdpStringWithStream1());
3138 std::vector
<std::string
> initial_ufrags
= GetUfrags(pc_
->local_description());
3140 // Call SetConfiguration with a config identical to what the PC was
3141 // constructed with.
3142 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
3143 CreateOfferAsLocalDescription();
3145 // Grab the new ufrags.
3146 std::vector
<std::string
> subsequent_ufrags
=
3147 GetUfrags(pc_
->local_description());
3149 EXPECT_EQ(initial_ufrags
, subsequent_ufrags
);
3152 // Test for a weird corner case scenario:
3153 // 1. Audio/video session established.
3154 // 2. SetConfiguration changes ICE config; ICE restart needed.
3155 // 3. ICE restart initiated by remote peer, but only for one m= section.
3156 // 4. Next createOffer should initiate an ICE restart, but only for the other
3157 // m= section; it would be pointless to do an ICE restart for the m= section
3158 // that was already restarted.
3159 TEST_P(PeerConnectionInterfaceTest
, SetConfigurationCausingPartialIceRestart
) {
3160 PeerConnectionInterface::RTCConfiguration config
;
3161 config
.sdp_semantics
= sdp_semantics_
;
3162 config
.type
= PeerConnectionInterface::kRelay
;
3163 CreatePeerConnection(config
);
3164 config
= pc_
->GetConfiguration();
3165 AddAudioTrack(kAudioTracks
[0], {kStreamId1
});
3166 AddVideoTrack(kVideoTracks
[0], {kStreamId1
});
3168 // Do initial offer/answer so there's something to restart.
3169 CreateOfferAsLocalDescription();
3170 CreateAnswerAsRemoteDescription(GetSdpStringWithStream1());
3172 // Change ICE policy, which should set the "needs-ice-restart" flag.
3173 config
.type
= PeerConnectionInterface::kAll
;
3174 EXPECT_TRUE(pc_
->SetConfiguration(config
).ok());
3176 // Do ICE restart for the first m= section, initiated by remote peer.
3177 std::unique_ptr
<webrtc::SessionDescriptionInterface
> remote_offer(
3178 webrtc::CreateSessionDescription(SdpType::kOffer
,
3179 GetSdpStringWithStream1(), nullptr));
3180 ASSERT_TRUE(remote_offer
);
3181 remote_offer
->description()->transport_infos()[0].description
.ice_ufrag
=
3183 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_offer
)));
3184 CreateAnswerAsLocalDescription();
3187 std::vector
<std::string
> initial_ufrags
= GetUfrags(pc_
->local_description());
3188 ASSERT_EQ(2U, initial_ufrags
.size());
3190 // Create offer and grab the new ufrags.
3191 CreateOfferAsLocalDescription();
3192 std::vector
<std::string
> subsequent_ufrags
=
3193 GetUfrags(pc_
->local_description());
3194 ASSERT_EQ(2U, subsequent_ufrags
.size());
3196 // Ensure that only the ufrag for the second m= section changed.
3197 EXPECT_EQ(initial_ufrags
[0], subsequent_ufrags
[0]);
3198 EXPECT_NE(initial_ufrags
[1], subsequent_ufrags
[1]);
3201 // Tests that the methods to return current/pending descriptions work as
3202 // expected at different points in the offer/answer exchange. This test does
3203 // one offer/answer exchange as the offerer, then another as the answerer.
3204 TEST_P(PeerConnectionInterfaceTest
, CurrentAndPendingDescriptions
) {
3205 // This disables DTLS so we can apply an answer to ourselves.
3206 CreatePeerConnection();
3208 // Create initial local offer and get SDP (which will also be used as
3209 // answer/pranswer);
3210 std::unique_ptr
<SessionDescriptionInterface
> local_offer
;
3211 ASSERT_TRUE(DoCreateOffer(&local_offer
, nullptr));
3213 EXPECT_TRUE(local_offer
->ToString(&sdp
));
3216 SessionDescriptionInterface
* local_offer_ptr
= local_offer
.get();
3217 EXPECT_TRUE(DoSetLocalDescription(std::move(local_offer
)));
3218 EXPECT_EQ(local_offer_ptr
, pc_
->pending_local_description());
3219 EXPECT_EQ(nullptr, pc_
->pending_remote_description());
3220 EXPECT_EQ(nullptr, pc_
->current_local_description());
3221 EXPECT_EQ(nullptr, pc_
->current_remote_description());
3223 // Set remote pranswer.
3224 std::unique_ptr
<SessionDescriptionInterface
> remote_pranswer(
3225 webrtc::CreateSessionDescription(SdpType::kPrAnswer
, sdp
));
3226 SessionDescriptionInterface
* remote_pranswer_ptr
= remote_pranswer
.get();
3227 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_pranswer
)));
3228 EXPECT_EQ(local_offer_ptr
, pc_
->pending_local_description());
3229 EXPECT_EQ(remote_pranswer_ptr
, pc_
->pending_remote_description());
3230 EXPECT_EQ(nullptr, pc_
->current_local_description());
3231 EXPECT_EQ(nullptr, pc_
->current_remote_description());
3233 // Set remote answer.
3234 std::unique_ptr
<SessionDescriptionInterface
> remote_answer(
3235 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
3236 SessionDescriptionInterface
* remote_answer_ptr
= remote_answer
.get();
3237 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_answer
)));
3238 EXPECT_EQ(nullptr, pc_
->pending_local_description());
3239 EXPECT_EQ(nullptr, pc_
->pending_remote_description());
3240 EXPECT_EQ(local_offer_ptr
, pc_
->current_local_description());
3241 EXPECT_EQ(remote_answer_ptr
, pc_
->current_remote_description());
3243 // Set remote offer.
3244 std::unique_ptr
<SessionDescriptionInterface
> remote_offer(
3245 webrtc::CreateSessionDescription(SdpType::kOffer
, sdp
));
3246 SessionDescriptionInterface
* remote_offer_ptr
= remote_offer
.get();
3247 EXPECT_TRUE(DoSetRemoteDescription(std::move(remote_offer
)));
3248 EXPECT_EQ(remote_offer_ptr
, pc_
->pending_remote_description());
3249 EXPECT_EQ(nullptr, pc_
->pending_local_description());
3250 EXPECT_EQ(local_offer_ptr
, pc_
->current_local_description());
3251 EXPECT_EQ(remote_answer_ptr
, pc_
->current_remote_description());
3253 // Set local pranswer.
3254 std::unique_ptr
<SessionDescriptionInterface
> local_pranswer(
3255 webrtc::CreateSessionDescription(SdpType::kPrAnswer
, sdp
));
3256 SessionDescriptionInterface
* local_pranswer_ptr
= local_pranswer
.get();
3257 EXPECT_TRUE(DoSetLocalDescription(std::move(local_pranswer
)));
3258 EXPECT_EQ(remote_offer_ptr
, pc_
->pending_remote_description());
3259 EXPECT_EQ(local_pranswer_ptr
, pc_
->pending_local_description());
3260 EXPECT_EQ(local_offer_ptr
, pc_
->current_local_description());
3261 EXPECT_EQ(remote_answer_ptr
, pc_
->current_remote_description());
3263 // Set local answer.
3264 std::unique_ptr
<SessionDescriptionInterface
> local_answer(
3265 webrtc::CreateSessionDescription(SdpType::kAnswer
, sdp
));
3266 SessionDescriptionInterface
* local_answer_ptr
= local_answer
.get();
3267 EXPECT_TRUE(DoSetLocalDescription(std::move(local_answer
)));
3268 EXPECT_EQ(nullptr, pc_
->pending_remote_description());
3269 EXPECT_EQ(nullptr, pc_
->pending_local_description());
3270 EXPECT_EQ(remote_offer_ptr
, pc_
->current_remote_description());
3271 EXPECT_EQ(local_answer_ptr
, pc_
->current_local_description());
3274 // Tests that it won't crash when calling StartRtcEventLog or StopRtcEventLog
3275 // after the PeerConnection is closed.
3276 // This version tests the StartRtcEventLog version that receives an object
3277 // of type `RtcEventLogOutput`.
3278 TEST_P(PeerConnectionInterfaceTest
,
3279 StartAndStopLoggingToOutputAfterPeerConnectionClosed
) {
3280 CreatePeerConnection();
3281 // The RtcEventLog will be reset when the PeerConnection is closed.
3285 pc_
->StartRtcEventLog(std::make_unique
<webrtc::RtcEventLogOutputNull
>(),
3286 webrtc::RtcEventLog::kImmediateOutput
));
3287 pc_
->StopRtcEventLog();
3290 // Test that generated offers/answers include "ice-option:trickle".
3291 TEST_P(PeerConnectionInterfaceTest
, OffersAndAnswersHaveTrickleIceOption
) {
3292 CreatePeerConnection();
3294 // First, create an offer with audio/video.
3295 RTCOfferAnswerOptions options
;
3296 options
.offer_to_receive_audio
= 1;
3297 options
.offer_to_receive_video
= 1;
3298 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3299 ASSERT_TRUE(DoCreateOffer(&offer
, &options
));
3300 cricket::SessionDescription
* desc
= offer
->description();
3301 ASSERT_EQ(2u, desc
->transport_infos().size());
3302 EXPECT_TRUE(desc
->transport_infos()[0].description
.HasOption("trickle"));
3303 EXPECT_TRUE(desc
->transport_infos()[1].description
.HasOption("trickle"));
3305 // Apply the offer as a remote description, then create an answer.
3306 EXPECT_FALSE(pc_
->can_trickle_ice_candidates());
3307 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
3308 ASSERT_TRUE(pc_
->can_trickle_ice_candidates());
3309 EXPECT_TRUE(*(pc_
->can_trickle_ice_candidates()));
3310 std::unique_ptr
<SessionDescriptionInterface
> answer
;
3311 ASSERT_TRUE(DoCreateAnswer(&answer
, &options
));
3312 desc
= answer
->description();
3313 ASSERT_EQ(2u, desc
->transport_infos().size());
3314 EXPECT_TRUE(desc
->transport_infos()[0].description
.HasOption("trickle"));
3315 EXPECT_TRUE(desc
->transport_infos()[1].description
.HasOption("trickle"));
3318 // Test that ICE renomination isn't offered if it's not enabled in the PC's
3319 // RTCConfiguration.
3320 TEST_P(PeerConnectionInterfaceTest
, IceRenominationNotOffered
) {
3321 PeerConnectionInterface::RTCConfiguration config
;
3322 config
.sdp_semantics
= sdp_semantics_
;
3323 config
.enable_ice_renomination
= false;
3324 CreatePeerConnection(config
);
3325 AddAudioTrack("foo");
3327 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3328 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3329 cricket::SessionDescription
* desc
= offer
->description();
3330 EXPECT_EQ(1u, desc
->transport_infos().size());
3332 desc
->transport_infos()[0].description
.GetIceParameters().renomination
);
3335 // Test that the ICE renomination option is present in generated offers/answers
3336 // if it's enabled in the PC's RTCConfiguration.
3337 TEST_P(PeerConnectionInterfaceTest
, IceRenominationOptionInOfferAndAnswer
) {
3338 PeerConnectionInterface::RTCConfiguration config
;
3339 config
.sdp_semantics
= sdp_semantics_
;
3340 config
.enable_ice_renomination
= true;
3341 CreatePeerConnection(config
);
3342 AddAudioTrack("foo");
3344 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3345 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3346 cricket::SessionDescription
* desc
= offer
->description();
3347 EXPECT_EQ(1u, desc
->transport_infos().size());
3349 desc
->transport_infos()[0].description
.GetIceParameters().renomination
);
3351 // Set the offer as a remote description, then create an answer and ensure it
3352 // has the renomination flag too.
3353 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
3354 std::unique_ptr
<SessionDescriptionInterface
> answer
;
3355 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
3356 desc
= answer
->description();
3357 EXPECT_EQ(1u, desc
->transport_infos().size());
3359 desc
->transport_infos()[0].description
.GetIceParameters().renomination
);
3362 // Test that if CreateOffer is called with the deprecated "offer to receive
3363 // audio/video" constraints, they're processed and result in an offer with
3364 // audio/video sections just as if RTCOfferAnswerOptions had been used.
3365 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithOfferToReceiveConstraints
) {
3366 CreatePeerConnection();
3368 RTCOfferAnswerOptions options
;
3369 options
.offer_to_receive_audio
= 1;
3370 options
.offer_to_receive_video
= 1;
3371 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3372 ASSERT_TRUE(DoCreateOffer(&offer
, &options
));
3374 cricket::SessionDescription
* desc
= offer
->description();
3375 const cricket::ContentInfo
* audio
= cricket::GetFirstAudioContent(desc
);
3376 const cricket::ContentInfo
* video
= cricket::GetFirstVideoContent(desc
);
3377 ASSERT_NE(nullptr, audio
);
3378 ASSERT_NE(nullptr, video
);
3379 EXPECT_FALSE(audio
->rejected
);
3380 EXPECT_FALSE(video
->rejected
);
3383 // Test that if CreateAnswer is called with the deprecated "offer to receive
3384 // audio/video" constraints, they're processed and can be used to reject an
3385 // offered m= section just as can be done with RTCOfferAnswerOptions;
3386 // Don't run under Unified Plan since this behavior is not supported.
3387 TEST_F(PeerConnectionInterfaceTestPlanB
,
3388 CreateAnswerWithOfferToReceiveConstraints
) {
3389 CreatePeerConnection();
3391 // First, create an offer with audio/video and apply it as a remote
3393 RTCOfferAnswerOptions options
;
3394 options
.offer_to_receive_audio
= 1;
3395 options
.offer_to_receive_video
= 1;
3396 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3397 ASSERT_TRUE(DoCreateOffer(&offer
, &options
));
3398 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
3400 // Now create answer that rejects audio/video.
3401 options
.offer_to_receive_audio
= 0;
3402 options
.offer_to_receive_video
= 0;
3403 std::unique_ptr
<SessionDescriptionInterface
> answer
;
3404 ASSERT_TRUE(DoCreateAnswer(&answer
, &options
));
3406 cricket::SessionDescription
* desc
= answer
->description();
3407 const cricket::ContentInfo
* audio
= cricket::GetFirstAudioContent(desc
);
3408 const cricket::ContentInfo
* video
= cricket::GetFirstVideoContent(desc
);
3409 ASSERT_NE(nullptr, audio
);
3410 ASSERT_NE(nullptr, video
);
3411 EXPECT_TRUE(audio
->rejected
);
3412 EXPECT_TRUE(video
->rejected
);
3415 // Test that negotiation can succeed with a data channel only, and with the max
3416 // bundle policy. Previously there was a bug that prevented this.
3417 #ifdef WEBRTC_HAVE_SCTP
3418 TEST_P(PeerConnectionInterfaceTest
, DataChannelOnlyOfferWithMaxBundlePolicy
) {
3420 TEST_P(PeerConnectionInterfaceTest
,
3421 DISABLED_DataChannelOnlyOfferWithMaxBundlePolicy
) {
3422 #endif // WEBRTC_HAVE_SCTP
3423 PeerConnectionInterface::RTCConfiguration config
;
3424 config
.sdp_semantics
= sdp_semantics_
;
3425 config
.bundle_policy
= PeerConnectionInterface::kBundlePolicyMaxBundle
;
3426 CreatePeerConnection(config
);
3428 // First, create an offer with only a data channel and apply it as a remote
3430 pc_
->CreateDataChannelOrError("test", nullptr);
3431 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3432 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3433 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
3435 // Create and set answer as well.
3436 std::unique_ptr
<SessionDescriptionInterface
> answer
;
3437 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
3438 EXPECT_TRUE(DoSetLocalDescription(std::move(answer
)));
3441 TEST_P(PeerConnectionInterfaceTest
, SetBitrateWithoutMinSucceeds
) {
3442 CreatePeerConnection();
3443 BitrateSettings bitrate
;
3444 bitrate
.start_bitrate_bps
= 100000;
3445 EXPECT_TRUE(pc_
->SetBitrate(bitrate
).ok());
3448 TEST_P(PeerConnectionInterfaceTest
, SetBitrateNegativeMinFails
) {
3449 CreatePeerConnection();
3450 BitrateSettings bitrate
;
3451 bitrate
.min_bitrate_bps
= -1;
3452 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3455 TEST_P(PeerConnectionInterfaceTest
, SetBitrateCurrentLessThanMinFails
) {
3456 CreatePeerConnection();
3457 BitrateSettings bitrate
;
3458 bitrate
.min_bitrate_bps
= 5;
3459 bitrate
.start_bitrate_bps
= 3;
3460 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3463 TEST_P(PeerConnectionInterfaceTest
, SetBitrateCurrentNegativeFails
) {
3464 CreatePeerConnection();
3465 BitrateSettings bitrate
;
3466 bitrate
.start_bitrate_bps
= -1;
3467 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3470 TEST_P(PeerConnectionInterfaceTest
, SetBitrateMaxLessThanCurrentFails
) {
3471 CreatePeerConnection();
3472 BitrateSettings bitrate
;
3473 bitrate
.start_bitrate_bps
= 10;
3474 bitrate
.max_bitrate_bps
= 8;
3475 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3478 TEST_P(PeerConnectionInterfaceTest
, SetBitrateMaxLessThanMinFails
) {
3479 CreatePeerConnection();
3480 BitrateSettings bitrate
;
3481 bitrate
.min_bitrate_bps
= 10;
3482 bitrate
.max_bitrate_bps
= 8;
3483 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3486 TEST_P(PeerConnectionInterfaceTest
, SetBitrateMaxNegativeFails
) {
3487 CreatePeerConnection();
3488 BitrateSettings bitrate
;
3489 bitrate
.max_bitrate_bps
= -1;
3490 EXPECT_FALSE(pc_
->SetBitrate(bitrate
).ok());
3493 // The current bitrate from BitrateSettings is currently clamped
3494 // by Call's BitrateConstraints, which comes from the SDP or a default value.
3495 // This test checks that a call to SetBitrate with a current bitrate that will
3496 // be clamped succeeds.
3497 TEST_P(PeerConnectionInterfaceTest
, SetBitrateCurrentLessThanImplicitMin
) {
3498 CreatePeerConnection();
3499 BitrateSettings bitrate
;
3500 bitrate
.start_bitrate_bps
= 1;
3501 EXPECT_TRUE(pc_
->SetBitrate(bitrate
).ok());
3504 // The following tests verify that the offer can be created correctly.
3505 TEST_P(PeerConnectionInterfaceTest
,
3506 CreateOfferFailsWithInvalidOfferToReceiveAudio
) {
3507 RTCOfferAnswerOptions rtc_options
;
3509 // Setting offer_to_receive_audio to a value lower than kUndefined or greater
3510 // than kMaxOfferToReceiveMedia should be treated as invalid.
3511 rtc_options
.offer_to_receive_audio
= RTCOfferAnswerOptions::kUndefined
- 1;
3512 CreatePeerConnection();
3513 EXPECT_FALSE(CreateOfferWithOptions(rtc_options
));
3515 rtc_options
.offer_to_receive_audio
=
3516 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia
+ 1;
3517 EXPECT_FALSE(CreateOfferWithOptions(rtc_options
));
3520 TEST_P(PeerConnectionInterfaceTest
,
3521 CreateOfferFailsWithInvalidOfferToReceiveVideo
) {
3522 RTCOfferAnswerOptions rtc_options
;
3524 // Setting offer_to_receive_video to a value lower than kUndefined or greater
3525 // than kMaxOfferToReceiveMedia should be treated as invalid.
3526 rtc_options
.offer_to_receive_video
= RTCOfferAnswerOptions::kUndefined
- 1;
3527 CreatePeerConnection();
3528 EXPECT_FALSE(CreateOfferWithOptions(rtc_options
));
3530 rtc_options
.offer_to_receive_video
=
3531 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia
+ 1;
3532 EXPECT_FALSE(CreateOfferWithOptions(rtc_options
));
3535 // Test that the audio and video content will be added to an offer if both
3536 // `offer_to_receive_audio` and `offer_to_receive_video` options are 1.
3537 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithAudioVideoOptions
) {
3538 RTCOfferAnswerOptions rtc_options
;
3539 rtc_options
.offer_to_receive_audio
= 1;
3540 rtc_options
.offer_to_receive_video
= 1;
3542 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3543 CreatePeerConnection();
3544 offer
= CreateOfferWithOptions(rtc_options
);
3546 EXPECT_NE(nullptr, GetFirstAudioContent(offer
->description()));
3547 EXPECT_NE(nullptr, GetFirstVideoContent(offer
->description()));
3550 // Test that only audio content will be added to the offer if only
3551 // `offer_to_receive_audio` options is 1.
3552 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithAudioOnlyOptions
) {
3553 RTCOfferAnswerOptions rtc_options
;
3554 rtc_options
.offer_to_receive_audio
= 1;
3555 rtc_options
.offer_to_receive_video
= 0;
3557 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3558 CreatePeerConnection();
3559 offer
= CreateOfferWithOptions(rtc_options
);
3561 EXPECT_NE(nullptr, GetFirstAudioContent(offer
->description()));
3562 EXPECT_EQ(nullptr, GetFirstVideoContent(offer
->description()));
3565 // Test that only video content will be added if only `offer_to_receive_video`
3567 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithVideoOnlyOptions
) {
3568 RTCOfferAnswerOptions rtc_options
;
3569 rtc_options
.offer_to_receive_audio
= 0;
3570 rtc_options
.offer_to_receive_video
= 1;
3572 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3573 CreatePeerConnection();
3574 offer
= CreateOfferWithOptions(rtc_options
);
3576 EXPECT_EQ(nullptr, GetFirstAudioContent(offer
->description()));
3577 EXPECT_NE(nullptr, GetFirstVideoContent(offer
->description()));
3580 // Test that no media content will be added to the offer if using default
3581 // RTCOfferAnswerOptions.
3582 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithDefaultOfferAnswerOptions
) {
3583 RTCOfferAnswerOptions rtc_options
;
3585 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3586 CreatePeerConnection();
3587 offer
= CreateOfferWithOptions(rtc_options
);
3589 EXPECT_EQ(nullptr, GetFirstAudioContent(offer
->description()));
3590 EXPECT_EQ(nullptr, GetFirstVideoContent(offer
->description()));
3593 // Test that if `ice_restart` is true, the ufrag/pwd will change, otherwise
3594 // ufrag/pwd will be the same in the new offer.
3595 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithIceRestart
) {
3596 CreatePeerConnection();
3598 RTCOfferAnswerOptions rtc_options
;
3599 rtc_options
.ice_restart
= false;
3600 rtc_options
.offer_to_receive_audio
= 1;
3602 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3603 CreateOfferWithOptionsAsLocalDescription(&offer
, rtc_options
);
3604 std::string mid
= cricket::GetFirstAudioContent(offer
->description())->name
;
3606 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_ufrag
;
3608 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_pwd
;
3610 // `ice_restart` is false, the ufrag/pwd shouldn't change.
3611 CreateOfferWithOptionsAsLocalDescription(&offer
, rtc_options
);
3613 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_ufrag
;
3615 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_pwd
;
3617 // `ice_restart` is true, the ufrag/pwd should change.
3618 rtc_options
.ice_restart
= true;
3619 CreateOfferWithOptionsAsLocalDescription(&offer
, rtc_options
);
3621 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_ufrag
;
3623 offer
->description()->GetTransportInfoByName(mid
)->description
.ice_pwd
;
3625 EXPECT_EQ(ufrag1
, ufrag2
);
3626 EXPECT_EQ(pwd1
, pwd2
);
3627 EXPECT_NE(ufrag2
, ufrag3
);
3628 EXPECT_NE(pwd2
, pwd3
);
3631 // Test that if `use_rtp_mux` is true, the bundling will be enabled in the
3632 // offer; if it is false, there won't be any bundle group in the offer.
3633 TEST_P(PeerConnectionInterfaceTest
, CreateOfferWithRtpMux
) {
3634 RTCOfferAnswerOptions rtc_options
;
3635 rtc_options
.offer_to_receive_audio
= 1;
3636 rtc_options
.offer_to_receive_video
= 1;
3638 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3639 CreatePeerConnection();
3641 rtc_options
.use_rtp_mux
= true;
3642 offer
= CreateOfferWithOptions(rtc_options
);
3644 EXPECT_NE(nullptr, GetFirstAudioContent(offer
->description()));
3645 EXPECT_NE(nullptr, GetFirstVideoContent(offer
->description()));
3646 EXPECT_TRUE(offer
->description()->HasGroup(cricket::GROUP_TYPE_BUNDLE
));
3648 rtc_options
.use_rtp_mux
= false;
3649 offer
= CreateOfferWithOptions(rtc_options
);
3651 EXPECT_NE(nullptr, GetFirstAudioContent(offer
->description()));
3652 EXPECT_NE(nullptr, GetFirstVideoContent(offer
->description()));
3653 EXPECT_FALSE(offer
->description()->HasGroup(cricket::GROUP_TYPE_BUNDLE
));
3656 // This test ensures OnRenegotiationNeeded is called when we add track with
3657 // MediaStream -> AddTrack in the same way it is called when we add track with
3658 // PeerConnection -> AddTrack.
3659 // The test can be removed once addStream is rewritten in terms of addTrack
3660 // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
3661 // Don't run under Unified Plan since the stream API is not available.
3662 TEST_F(PeerConnectionInterfaceTestPlanB
,
3663 MediaStreamAddTrackRemoveTrackRenegotiate
) {
3664 CreatePeerConnectionWithoutDtls();
3665 rtc::scoped_refptr
<MediaStreamInterface
> stream(
3666 pc_factory_
->CreateLocalMediaStream(kStreamId1
));
3667 pc_
->AddStream(stream
.get());
3668 rtc::scoped_refptr
<AudioTrackInterface
> audio_track(
3669 CreateAudioTrack("audio_track"));
3670 rtc::scoped_refptr
<VideoTrackInterface
> video_track(
3671 CreateVideoTrack("video_track"));
3672 stream
->AddTrack(audio_track
);
3673 EXPECT_TRUE_WAIT(observer_
.renegotiation_needed_
, kTimeout
);
3674 observer_
.renegotiation_needed_
= false;
3676 CreateOfferReceiveAnswer();
3677 stream
->AddTrack(video_track
);
3678 EXPECT_TRUE_WAIT(observer_
.renegotiation_needed_
, kTimeout
);
3679 observer_
.renegotiation_needed_
= false;
3681 CreateOfferReceiveAnswer();
3682 stream
->RemoveTrack(audio_track
);
3683 EXPECT_TRUE_WAIT(observer_
.renegotiation_needed_
, kTimeout
);
3684 observer_
.renegotiation_needed_
= false;
3686 CreateOfferReceiveAnswer();
3687 stream
->RemoveTrack(video_track
);
3688 EXPECT_TRUE_WAIT(observer_
.renegotiation_needed_
, kTimeout
);
3689 observer_
.renegotiation_needed_
= false;
3692 // Tests that an error is returned if a description is applied that has fewer
3693 // media sections than the existing description.
3694 TEST_P(PeerConnectionInterfaceTest
,
3695 MediaSectionCountEnforcedForSubsequentOffer
) {
3696 CreatePeerConnection();
3697 AddAudioTrack("audio_label");
3698 AddVideoTrack("video_label");
3700 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3701 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3702 EXPECT_TRUE(DoSetRemoteDescription(std::move(offer
)));
3704 // A remote offer with fewer media sections should be rejected.
3705 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3706 offer
->description()->contents().pop_back();
3707 offer
->description()->contents().pop_back();
3708 ASSERT_TRUE(offer
->description()->contents().empty());
3709 EXPECT_FALSE(DoSetRemoteDescription(std::move(offer
)));
3711 std::unique_ptr
<SessionDescriptionInterface
> answer
;
3712 ASSERT_TRUE(DoCreateAnswer(&answer
, nullptr));
3713 EXPECT_TRUE(DoSetLocalDescription(std::move(answer
)));
3715 // A subsequent local offer with fewer media sections should be rejected.
3716 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3717 offer
->description()->contents().pop_back();
3718 offer
->description()->contents().pop_back();
3719 ASSERT_TRUE(offer
->description()->contents().empty());
3720 EXPECT_FALSE(DoSetLocalDescription(std::move(offer
)));
3723 TEST_P(PeerConnectionInterfaceTest
, ExtmapAllowMixedIsConfigurable
) {
3724 RTCConfiguration config
;
3725 // Default behavior is true.
3726 CreatePeerConnection(config
);
3727 std::unique_ptr
<SessionDescriptionInterface
> offer
;
3728 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3729 EXPECT_TRUE(offer
->description()->extmap_allow_mixed());
3730 // Possible to set to false.
3731 config
.offer_extmap_allow_mixed
= false;
3732 CreatePeerConnection(config
);
3734 ASSERT_TRUE(DoCreateOffer(&offer
, nullptr));
3735 EXPECT_FALSE(offer
->description()->extmap_allow_mixed());
3738 TEST_P(PeerConnectionInterfaceTest
,
3739 RtpSenderSetDegradationPreferenceWithoutEncodings
) {
3740 CreatePeerConnection();
3741 AddVideoTrack("video_label");
3743 std::vector
<rtc::scoped_refptr
<RtpSenderInterface
>> rtp_senders
=
3745 ASSERT_EQ(rtp_senders
.size(), 1u);
3746 ASSERT_EQ(rtp_senders
[0]->media_type(), cricket::MEDIA_TYPE_VIDEO
);
3747 rtc::scoped_refptr
<RtpSenderInterface
> video_rtp_sender
= rtp_senders
[0];
3748 RtpParameters parameters
= video_rtp_sender
->GetParameters();
3749 ASSERT_NE(parameters
.degradation_preference
,
3750 DegradationPreference::MAINTAIN_RESOLUTION
);
3751 parameters
.degradation_preference
=
3752 DegradationPreference::MAINTAIN_RESOLUTION
;
3753 ASSERT_TRUE(video_rtp_sender
->SetParameters(parameters
).ok());
3755 std::unique_ptr
<SessionDescriptionInterface
> local_offer
;
3756 ASSERT_TRUE(DoCreateOffer(&local_offer
, nullptr));
3757 ASSERT_TRUE(DoSetLocalDescription(std::move(local_offer
)));
3759 RtpParameters parameters_new
= video_rtp_sender
->GetParameters();
3760 ASSERT_EQ(parameters_new
.degradation_preference
,
3761 DegradationPreference::MAINTAIN_RESOLUTION
);
3764 INSTANTIATE_TEST_SUITE_P(PeerConnectionInterfaceTest
,
3765 PeerConnectionInterfaceTest
,
3766 Values(SdpSemantics::kPlanB_DEPRECATED
,
3767 SdpSemantics::kUnifiedPlan
));
3769 class PeerConnectionMediaConfigTest
: public ::testing::Test
{
3771 void SetUp() override
{
3772 pcf_
= PeerConnectionFactoryForTest::CreatePeerConnectionFactoryForTest();
3774 const cricket::MediaConfig
TestCreatePeerConnection(
3775 const RTCConfiguration
& config
) {
3776 PeerConnectionDependencies
pc_dependencies(&observer_
);
3778 pcf_
->CreatePeerConnectionOrError(config
, std::move(pc_dependencies
));
3779 EXPECT_TRUE(result
.ok());
3780 observer_
.SetPeerConnectionInterface(result
.value().get());
3781 return result
.value()->GetConfiguration().media_config
;
3784 rtc::scoped_refptr
<PeerConnectionFactoryForTest
> pcf_
;
3785 MockPeerConnectionObserver observer_
;
3788 // This sanity check validates the test infrastructure itself.
3789 TEST_F(PeerConnectionMediaConfigTest
, TestCreateAndClose
) {
3790 PeerConnectionInterface::RTCConfiguration config
;
3791 config
.sdp_semantics
= SdpSemantics::kUnifiedPlan
;
3792 PeerConnectionDependencies
pc_dependencies(&observer_
);
3794 pcf_
->CreatePeerConnectionOrError(config
, std::move(pc_dependencies
));
3795 EXPECT_TRUE(result
.ok());
3796 observer_
.SetPeerConnectionInterface(result
.value().get());
3797 result
.value()->Close(); // No abort -> ok.
3801 // This test verifies the default behaviour with no constraints and a
3802 // default RTCConfiguration.
3803 TEST_F(PeerConnectionMediaConfigTest
, TestDefaults
) {
3804 PeerConnectionInterface::RTCConfiguration config
;
3805 config
.sdp_semantics
= SdpSemantics::kUnifiedPlan
;
3807 const cricket::MediaConfig
& media_config
= TestCreatePeerConnection(config
);
3809 EXPECT_TRUE(media_config
.enable_dscp
);
3810 EXPECT_TRUE(media_config
.video
.enable_cpu_adaptation
);
3811 EXPECT_TRUE(media_config
.video
.enable_prerenderer_smoothing
);
3812 EXPECT_FALSE(media_config
.video
.suspend_below_min_bitrate
);
3813 EXPECT_FALSE(media_config
.video
.experiment_cpu_load_estimator
);
3816 // This test verifies that the enable_prerenderer_smoothing flag is
3817 // propagated from RTCConfiguration to the PeerConnection.
3818 TEST_F(PeerConnectionMediaConfigTest
, TestDisablePrerendererSmoothingTrue
) {
3819 PeerConnectionInterface::RTCConfiguration config
;
3820 config
.sdp_semantics
= SdpSemantics::kUnifiedPlan
;
3822 config
.set_prerenderer_smoothing(false);
3823 const cricket::MediaConfig
& media_config
= TestCreatePeerConnection(config
);
3825 EXPECT_FALSE(media_config
.video
.enable_prerenderer_smoothing
);
3828 // This test verifies that the experiment_cpu_load_estimator flag is
3829 // propagated from RTCConfiguration to the PeerConnection.
3830 TEST_F(PeerConnectionMediaConfigTest
, TestEnableExperimentCpuLoadEstimator
) {
3831 PeerConnectionInterface::RTCConfiguration config
;
3832 config
.sdp_semantics
= SdpSemantics::kUnifiedPlan
;
3834 config
.set_experiment_cpu_load_estimator(true);
3835 const cricket::MediaConfig
& media_config
= TestCreatePeerConnection(config
);
3837 EXPECT_TRUE(media_config
.video
.experiment_cpu_load_estimator
);
3840 // Tests a few random fields being different.
3841 TEST(RTCConfigurationTest
, ComparisonOperators
) {
3842 PeerConnectionInterface::RTCConfiguration a
;
3843 PeerConnectionInterface::RTCConfiguration b
;
3846 PeerConnectionInterface::RTCConfiguration c
;
3847 c
.servers
.push_back(PeerConnectionInterface::IceServer());
3850 PeerConnectionInterface::RTCConfiguration d
;
3851 d
.type
= PeerConnectionInterface::kRelay
;
3854 PeerConnectionInterface::RTCConfiguration e
;
3855 e
.audio_jitter_buffer_max_packets
= 5;
3858 PeerConnectionInterface::RTCConfiguration f
;
3859 f
.ice_connection_receiving_timeout
= 1337;
3862 PeerConnectionInterface::RTCConfiguration
h(
3863 PeerConnectionInterface::RTCConfigurationType::kAggressive
);
3868 } // namespace webrtc