blob: 116a598079dcc60547d0e2802b1bd96068509a95 [file] [log] [blame]
Steve Anton6f25b092017-10-23 09:39:20 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
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.
9 */
10
Karl Wiberg32df86e2017-11-03 10:24:27 +010011#include "api/audio_codecs/builtin_audio_decoder_factory.h"
12#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Steve Anton6f25b092017-10-23 09:39:20 -070013#include "api/peerconnectionproxy.h"
14#include "p2p/base/fakeportallocator.h"
15#include "p2p/base/teststunserver.h"
16#include "p2p/client/basicportallocator.h"
17#include "pc/mediasession.h"
18#include "pc/peerconnection.h"
19#include "pc/peerconnectionwrapper.h"
20#include "pc/sdputils.h"
21#ifdef WEBRTC_ANDROID
22#include "pc/test/androidtestinitializer.h"
23#endif
24#include "pc/test/fakeaudiocapturemodule.h"
25#include "rtc_base/fakenetwork.h"
26#include "rtc_base/gunit.h"
27#include "rtc_base/ptr_util.h"
28#include "rtc_base/virtualsocketserver.h"
29#include "test/gmock.h"
30
31namespace webrtc {
32
33using BundlePolicy = PeerConnectionInterface::BundlePolicy;
34using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
35using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
36using RtcpMuxPolicy = PeerConnectionInterface::RtcpMuxPolicy;
37using rtc::SocketAddress;
Steve Anton7464fca2018-01-19 11:10:37 -080038using ::testing::Combine;
Steve Anton6f25b092017-10-23 09:39:20 -070039using ::testing::ElementsAre;
40using ::testing::UnorderedElementsAre;
41using ::testing::Values;
42
43constexpr int kDefaultTimeout = 10000;
44
45// TODO(steveanton): These tests should be rewritten to use the standard
46// RtpSenderInterface/DtlsTransportInterface objects once they're available in
47// the API. The RtpSender can be used to determine which transport a given media
48// will use: https://www.w3.org/TR/webrtc/#dom-rtcrtpsender-transport
Steve Anton7464fca2018-01-19 11:10:37 -080049// Should also be able to remove GetTransceiversForTesting at that point.
Steve Anton6f25b092017-10-23 09:39:20 -070050
51class PeerConnectionWrapperForBundleTest : public PeerConnectionWrapper {
52 public:
53 using PeerConnectionWrapper::PeerConnectionWrapper;
54
55 bool AddIceCandidateToMedia(cricket::Candidate* candidate,
56 cricket::MediaType media_type) {
57 auto* desc = pc()->remote_description()->description();
58 for (size_t i = 0; i < desc->contents().size(); i++) {
59 const auto& content = desc->contents()[i];
Steve Antonb1c1de12017-12-21 15:14:30 -080060 if (content.media_description()->type() == media_type) {
Steve Anton6f25b092017-10-23 09:39:20 -070061 candidate->set_transport_name(content.name);
62 JsepIceCandidate jsep_candidate(content.name, i, *candidate);
63 return pc()->AddIceCandidate(&jsep_candidate);
64 }
65 }
66 RTC_NOTREACHED();
67 return false;
68 }
69
70 rtc::PacketTransportInternal* voice_rtp_transport_channel() {
71 return (voice_channel() ? voice_channel()->rtp_dtls_transport() : nullptr);
72 }
73
74 rtc::PacketTransportInternal* voice_rtcp_transport_channel() {
75 return (voice_channel() ? voice_channel()->rtcp_dtls_transport() : nullptr);
76 }
77
78 cricket::VoiceChannel* voice_channel() {
Steve Anton7464fca2018-01-19 11:10:37 -080079 auto transceivers =
80 GetInternalPeerConnection()->GetTransceiversForTesting();
81 for (auto transceiver : transceivers) {
Steve Anton69470252018-02-09 11:43:08 -080082 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Steve Anton7464fca2018-01-19 11:10:37 -080083 return static_cast<cricket::VoiceChannel*>(
84 transceiver->internal()->channel());
85 }
86 }
87 return nullptr;
Steve Anton6f25b092017-10-23 09:39:20 -070088 }
89
90 rtc::PacketTransportInternal* video_rtp_transport_channel() {
91 return (video_channel() ? video_channel()->rtp_dtls_transport() : nullptr);
92 }
93
94 rtc::PacketTransportInternal* video_rtcp_transport_channel() {
95 return (video_channel() ? video_channel()->rtcp_dtls_transport() : nullptr);
96 }
97
98 cricket::VideoChannel* video_channel() {
Steve Anton7464fca2018-01-19 11:10:37 -080099 auto transceivers =
100 GetInternalPeerConnection()->GetTransceiversForTesting();
101 for (auto transceiver : transceivers) {
Steve Anton69470252018-02-09 11:43:08 -0800102 if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
Steve Anton7464fca2018-01-19 11:10:37 -0800103 return static_cast<cricket::VideoChannel*>(
104 transceiver->internal()->channel());
105 }
106 }
107 return nullptr;
Steve Anton6f25b092017-10-23 09:39:20 -0700108 }
109
110 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100111 auto* pci =
112 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
113 pc());
114 return static_cast<PeerConnection*>(pci->internal());
Steve Anton6f25b092017-10-23 09:39:20 -0700115 }
116
117 // Returns true if the stats indicate that an ICE connection is either in
118 // progress or established with the given remote address.
119 bool HasConnectionWithRemoteAddress(const SocketAddress& address) {
120 auto report = GetStats();
121 if (!report) {
122 return false;
123 }
124 std::string matching_candidate_id;
125 for (auto* ice_candidate_stats :
126 report->GetStatsOfType<RTCRemoteIceCandidateStats>()) {
127 if (*ice_candidate_stats->ip == address.HostAsURIString() &&
128 *ice_candidate_stats->port == address.port()) {
129 matching_candidate_id = ice_candidate_stats->id();
130 break;
131 }
132 }
133 if (matching_candidate_id.empty()) {
134 return false;
135 }
136 for (auto* pair_stats :
137 report->GetStatsOfType<RTCIceCandidatePairStats>()) {
138 if (*pair_stats->remote_candidate_id == matching_candidate_id) {
139 if (*pair_stats->state == RTCStatsIceCandidatePairState::kInProgress ||
140 *pair_stats->state == RTCStatsIceCandidatePairState::kSucceeded) {
141 return true;
142 }
143 }
144 }
145 return false;
146 }
147
148 rtc::FakeNetworkManager* network() { return network_; }
149
150 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
151
152 private:
153 rtc::FakeNetworkManager* network_;
154};
155
Steve Anton7464fca2018-01-19 11:10:37 -0800156class PeerConnectionBundleBaseTest : public ::testing::Test {
Steve Anton6f25b092017-10-23 09:39:20 -0700157 protected:
158 typedef std::unique_ptr<PeerConnectionWrapperForBundleTest> WrapperPtr;
159
Steve Anton7464fca2018-01-19 11:10:37 -0800160 explicit PeerConnectionBundleBaseTest(SdpSemantics sdp_semantics)
161 : vss_(new rtc::VirtualSocketServer()),
162 main_(vss_.get()),
163 sdp_semantics_(sdp_semantics) {
Steve Anton6f25b092017-10-23 09:39:20 -0700164#ifdef WEBRTC_ANDROID
165 InitializeAndroidObjects();
166#endif
167 pc_factory_ = CreatePeerConnectionFactory(
168 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Karl Wiberg32df86e2017-11-03 10:24:27 +0100169 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
170 CreateBuiltinAudioDecoderFactory(), nullptr, nullptr);
Steve Anton6f25b092017-10-23 09:39:20 -0700171 }
172
173 WrapperPtr CreatePeerConnection() {
174 return CreatePeerConnection(RTCConfiguration());
175 }
176
177 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
178 auto* fake_network = NewFakeNetwork();
179 auto port_allocator =
180 rtc::MakeUnique<cricket::BasicPortAllocator>(fake_network);
181 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
182 cricket::PORTALLOCATOR_DISABLE_RELAY);
183 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
184 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
Steve Anton7464fca2018-01-19 11:10:37 -0800185 RTCConfiguration modified_config = config;
186 modified_config.sdp_semantics = sdp_semantics_;
Steve Anton6f25b092017-10-23 09:39:20 -0700187 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton7464fca2018-01-19 11:10:37 -0800188 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Anton6f25b092017-10-23 09:39:20 -0700189 if (!pc) {
190 return nullptr;
191 }
192
193 auto wrapper = rtc::MakeUnique<PeerConnectionWrapperForBundleTest>(
194 pc_factory_, pc, std::move(observer));
195 wrapper->set_network(fake_network);
196 return wrapper;
197 }
198
199 // Accepts the same arguments as CreatePeerConnection and adds default audio
200 // and video tracks.
201 template <typename... Args>
202 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
203 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
204 if (!wrapper) {
205 return nullptr;
206 }
207 wrapper->AddAudioTrack("a");
208 wrapper->AddVideoTrack("v");
209 return wrapper;
210 }
211
212 cricket::Candidate CreateLocalUdpCandidate(
213 const rtc::SocketAddress& address) {
214 cricket::Candidate candidate;
215 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
216 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
217 candidate.set_address(address);
218 candidate.set_type(cricket::LOCAL_PORT_TYPE);
219 return candidate;
220 }
221
222 rtc::FakeNetworkManager* NewFakeNetwork() {
223 // The PeerConnection's port allocator is tied to the PeerConnection's
224 // lifetime and expects the underlying NetworkManager to outlive it. If
225 // PeerConnectionWrapper owned the NetworkManager, it would be destroyed
226 // before the PeerConnection (since subclass members are destroyed before
227 // base class members). Therefore, the test fixture will own all the fake
228 // networks even though tests should access the fake network through the
229 // PeerConnectionWrapper.
230 auto* fake_network = new rtc::FakeNetworkManager();
231 fake_networks_.emplace_back(fake_network);
232 return fake_network;
233 }
234
235 std::unique_ptr<rtc::VirtualSocketServer> vss_;
236 rtc::AutoSocketServerThread main_;
237 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
238 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton7464fca2018-01-19 11:10:37 -0800239 const SdpSemantics sdp_semantics_;
240};
241
242class PeerConnectionBundleTest
243 : public PeerConnectionBundleBaseTest,
244 public ::testing::WithParamInterface<SdpSemantics> {
245 protected:
246 PeerConnectionBundleTest() : PeerConnectionBundleBaseTest(GetParam()) {}
Steve Anton6f25b092017-10-23 09:39:20 -0700247};
248
249SdpContentMutator RemoveRtcpMux() {
250 return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
Steve Antonb1c1de12017-12-21 15:14:30 -0800251 content->media_description()->set_rtcp_mux(false);
Steve Anton6f25b092017-10-23 09:39:20 -0700252 };
253}
254
255std::vector<int> GetCandidateComponents(
256 const std::vector<IceCandidateInterface*> candidates) {
257 std::vector<int> components;
258 for (auto* candidate : candidates) {
259 components.push_back(candidate->candidate().component());
260 }
261 return components;
262}
263
264// Test that there are 2 local UDP candidates (1 RTP and 1 RTCP candidate) for
265// each media section when disabling bundling and disabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800266TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700267 TwoCandidatesForEachTransportWhenNoBundleNoRtcpMux) {
268 const SocketAddress kCallerAddress("1.1.1.1", 0);
269 const SocketAddress kCalleeAddress("2.2.2.2", 0);
270
271 RTCConfiguration config;
272 config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
273 auto caller = CreatePeerConnectionWithAudioVideo(config);
274 caller->network()->AddInterface(kCallerAddress);
275 auto callee = CreatePeerConnectionWithAudioVideo(config);
276 callee->network()->AddInterface(kCalleeAddress);
277
278 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
279 RTCOfferAnswerOptions options_no_bundle;
280 options_no_bundle.use_rtp_mux = false;
281 auto answer = callee->CreateAnswer(options_no_bundle);
282 SdpContentsForEach(RemoveRtcpMux(), answer->description());
283 ASSERT_TRUE(
284 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
285 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
286
287 // Check that caller has separate RTP and RTCP candidates for each media.
288 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
289 EXPECT_THAT(
290 GetCandidateComponents(caller->observer()->GetCandidatesByMline(0)),
291 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
292 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
293 EXPECT_THAT(
294 GetCandidateComponents(caller->observer()->GetCandidatesByMline(1)),
295 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
296 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
297
298 // Check that callee has separate RTP and RTCP candidates for each media.
299 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kDefaultTimeout);
300 EXPECT_THAT(
301 GetCandidateComponents(callee->observer()->GetCandidatesByMline(0)),
302 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
303 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
304 EXPECT_THAT(
305 GetCandidateComponents(callee->observer()->GetCandidatesByMline(1)),
306 UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
307 cricket::ICE_CANDIDATE_COMPONENT_RTCP));
308}
309
310// Test that there is 1 local UDP candidate for both RTP and RTCP for each media
311// section when disabling bundle but enabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800312TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700313 OneCandidateForEachTransportWhenNoBundleButRtcpMux) {
314 const SocketAddress kCallerAddress("1.1.1.1", 0);
315
316 auto caller = CreatePeerConnectionWithAudioVideo();
317 caller->network()->AddInterface(kCallerAddress);
318 auto callee = CreatePeerConnectionWithAudioVideo();
319
320 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
321 RTCOfferAnswerOptions options_no_bundle;
322 options_no_bundle.use_rtp_mux = false;
323 ASSERT_TRUE(
324 caller->SetRemoteDescription(callee->CreateAnswer(options_no_bundle)));
325
326 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
327
328 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
329 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(1).size());
330}
331
332// Test that there is 1 local UDP candidate in only the first media section when
333// bundling and enabling RTCP multiplexing.
Steve Anton7464fca2018-01-19 11:10:37 -0800334TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700335 OneCandidateOnlyOnFirstTransportWhenBundleAndRtcpMux) {
336 const SocketAddress kCallerAddress("1.1.1.1", 0);
337
338 RTCConfiguration config;
339 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
340 auto caller = CreatePeerConnectionWithAudioVideo(config);
341 caller->network()->AddInterface(kCallerAddress);
342 auto callee = CreatePeerConnectionWithAudioVideo(config);
343
344 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
345 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
346
347 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
348
349 EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
350 EXPECT_EQ(0u, caller->observer()->GetCandidatesByMline(1).size());
351}
352
353// The following parameterized test verifies that an offer/answer with varying
354// bundle policies and either bundle in the answer or not will produce the
355// expected RTP transports for audio and video. In particular, for bundling we
356// care about whether they are separate transports or the same.
357
358enum class BundleIncluded { kBundleInAnswer, kBundleNotInAnswer };
359std::ostream& operator<<(std::ostream& out, BundleIncluded value) {
360 switch (value) {
361 case BundleIncluded::kBundleInAnswer:
362 return out << "bundle in answer";
363 case BundleIncluded::kBundleNotInAnswer:
364 return out << "bundle not in answer";
365 }
366 return out << "unknown";
367}
368
369class PeerConnectionBundleMatrixTest
Steve Anton7464fca2018-01-19 11:10:37 -0800370 : public PeerConnectionBundleBaseTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700371 public ::testing::WithParamInterface<
Steve Anton7464fca2018-01-19 11:10:37 -0800372 std::tuple<SdpSemantics,
373 std::tuple<BundlePolicy, BundleIncluded, bool, bool>>> {
Steve Anton6f25b092017-10-23 09:39:20 -0700374 protected:
Steve Anton7464fca2018-01-19 11:10:37 -0800375 PeerConnectionBundleMatrixTest()
376 : PeerConnectionBundleBaseTest(std::get<0>(GetParam())) {
377 auto param = std::get<1>(GetParam());
378 bundle_policy_ = std::get<0>(param);
379 bundle_included_ = std::get<1>(param);
380 expected_same_before_ = std::get<2>(param);
381 expected_same_after_ = std::get<3>(param);
Steve Anton6f25b092017-10-23 09:39:20 -0700382 }
383
384 PeerConnectionInterface::BundlePolicy bundle_policy_;
385 BundleIncluded bundle_included_;
386 bool expected_same_before_;
387 bool expected_same_after_;
388};
389
390TEST_P(PeerConnectionBundleMatrixTest,
391 VerifyTransportsBeforeAndAfterSettingRemoteAnswer) {
392 RTCConfiguration config;
393 config.bundle_policy = bundle_policy_;
394 auto caller = CreatePeerConnectionWithAudioVideo(config);
395 auto callee = CreatePeerConnectionWithAudioVideo();
396
397 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
398 bool equal_before = (caller->voice_rtp_transport_channel() ==
399 caller->video_rtp_transport_channel());
400 EXPECT_EQ(expected_same_before_, equal_before);
401
402 RTCOfferAnswerOptions options;
403 options.use_rtp_mux = (bundle_included_ == BundleIncluded::kBundleInAnswer);
404 ASSERT_TRUE(
405 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
406 bool equal_after = (caller->voice_rtp_transport_channel() ==
407 caller->video_rtp_transport_channel());
408 EXPECT_EQ(expected_same_after_, equal_after);
409}
410
411// The max-bundle policy means we should anticipate bundling being negotiated,
412// and multiplex audio/video from the start.
413// For all other policies, bundling should only be enabled if negotiated by the
414// answer.
415INSTANTIATE_TEST_CASE_P(
416 PeerConnectionBundleTest,
417 PeerConnectionBundleMatrixTest,
Steve Anton7464fca2018-01-19 11:10:37 -0800418 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
419 Values(std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
420 BundleIncluded::kBundleInAnswer,
421 false,
422 true),
423 std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
424 BundleIncluded::kBundleNotInAnswer,
425 false,
426 false),
427 std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
428 BundleIncluded::kBundleInAnswer,
429 true,
430 true),
431 std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
432 BundleIncluded::kBundleNotInAnswer,
433 true,
434 true),
435 std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
436 BundleIncluded::kBundleInAnswer,
437 false,
438 true),
439 std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
440 BundleIncluded::kBundleNotInAnswer,
441 false,
442 false))));
Steve Anton6f25b092017-10-23 09:39:20 -0700443
444// Test that the audio/video transports on the callee side are the same before
445// and after setting a local answer when max BUNDLE is enabled and an offer with
446// BUNDLE is received.
Steve Anton7464fca2018-01-19 11:10:37 -0800447TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700448 TransportsSameForMaxBundleWithBundleInRemoteOffer) {
449 auto caller = CreatePeerConnectionWithAudioVideo();
450 RTCConfiguration config;
451 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
452 auto callee = CreatePeerConnectionWithAudioVideo(config);
453
454 RTCOfferAnswerOptions options_with_bundle;
455 options_with_bundle.use_rtp_mux = true;
456 ASSERT_TRUE(callee->SetRemoteDescription(
457 caller->CreateOfferAndSetAsLocal(options_with_bundle)));
458
459 EXPECT_EQ(callee->voice_rtp_transport_channel(),
460 callee->video_rtp_transport_channel());
461
462 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
463
464 EXPECT_EQ(callee->voice_rtp_transport_channel(),
465 callee->video_rtp_transport_channel());
466}
467
Steve Anton7464fca2018-01-19 11:10:37 -0800468TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700469 FailToSetRemoteOfferWithNoBundleWhenBundlePolicyMaxBundle) {
470 auto caller = CreatePeerConnectionWithAudioVideo();
471 RTCConfiguration config;
472 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
473 auto callee = CreatePeerConnectionWithAudioVideo(config);
474
475 RTCOfferAnswerOptions options_no_bundle;
476 options_no_bundle.use_rtp_mux = false;
477 EXPECT_FALSE(callee->SetRemoteDescription(
478 caller->CreateOfferAndSetAsLocal(options_no_bundle)));
479}
480
481// Test that if the media section which has the bundled transport is rejected,
482// then the peers still connect and the bundled transport switches to the other
483// media section.
484// Note: This is currently failing because of the following bug:
485// https://bugs.chromium.org/p/webrtc/issues/detail?id=6280
Steve Anton7464fca2018-01-19 11:10:37 -0800486TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700487 DISABLED_SuccessfullyNegotiateMaxBundleIfBundleTransportMediaRejected) {
488 RTCConfiguration config;
489 config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
490 auto caller = CreatePeerConnectionWithAudioVideo(config);
491 auto callee = CreatePeerConnection();
492 callee->AddVideoTrack("v");
493
494 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
495
496 RTCOfferAnswerOptions options;
497 options.offer_to_receive_audio = 0;
498 ASSERT_TRUE(
499 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
500
501 EXPECT_FALSE(caller->voice_rtp_transport_channel());
502 EXPECT_TRUE(caller->video_rtp_transport_channel());
503}
504
505// When requiring RTCP multiplexing, the PeerConnection never makes RTCP
506// transport channels.
Steve Anton7464fca2018-01-19 11:10:37 -0800507TEST_P(PeerConnectionBundleTest, NeverCreateRtcpTransportWithRtcpMuxRequired) {
Steve Anton6f25b092017-10-23 09:39:20 -0700508 RTCConfiguration config;
509 config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyRequire;
510 auto caller = CreatePeerConnectionWithAudioVideo(config);
511 auto callee = CreatePeerConnectionWithAudioVideo();
512
513 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
514
515 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
516 EXPECT_FALSE(caller->video_rtcp_transport_channel());
517
518 ASSERT_TRUE(
519 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
520
521 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
522 EXPECT_FALSE(caller->video_rtcp_transport_channel());
523}
524
525// When negotiating RTCP multiplexing, the PeerConnection makes RTCP transport
526// channels when the offer is sent, but will destroy them once the remote answer
527// is set.
Steve Anton7464fca2018-01-19 11:10:37 -0800528TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700529 CreateRtcpTransportOnlyBeforeAnswerWithRtcpMuxNegotiate) {
530 RTCConfiguration config;
531 config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyNegotiate;
532 auto caller = CreatePeerConnectionWithAudioVideo(config);
533 auto callee = CreatePeerConnectionWithAudioVideo();
534
535 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
536
537 EXPECT_TRUE(caller->voice_rtcp_transport_channel());
538 EXPECT_TRUE(caller->video_rtcp_transport_channel());
539
540 ASSERT_TRUE(
541 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
542
543 EXPECT_FALSE(caller->voice_rtcp_transport_channel());
544 EXPECT_FALSE(caller->video_rtcp_transport_channel());
545}
546
Steve Anton7464fca2018-01-19 11:10:37 -0800547TEST_P(PeerConnectionBundleTest, FailToSetDescriptionWithBundleAndNoRtcpMux) {
Steve Anton6f25b092017-10-23 09:39:20 -0700548 auto caller = CreatePeerConnectionWithAudioVideo();
549 auto callee = CreatePeerConnectionWithAudioVideo();
550
551 RTCOfferAnswerOptions options;
552 options.use_rtp_mux = true;
553
554 auto offer = caller->CreateOffer(options);
555 SdpContentsForEach(RemoveRtcpMux(), offer->description());
556
557 std::string error;
558 EXPECT_FALSE(caller->SetLocalDescription(CloneSessionDescription(offer.get()),
559 &error));
560 EXPECT_EQ(
561 "Failed to set local offer sdp: rtcp-mux must be enabled when BUNDLE is "
562 "enabled.",
563 error);
564
565 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
566 EXPECT_EQ(
567 "Failed to set remote offer sdp: rtcp-mux must be enabled when BUNDLE is "
568 "enabled.",
569 error);
570}
571
572// Test that candidates sent to the "video" transport do not get pushed down to
573// the "audio" transport channel when bundling.
Steve Anton7464fca2018-01-19 11:10:37 -0800574TEST_P(PeerConnectionBundleTest,
Steve Anton6f25b092017-10-23 09:39:20 -0700575 IgnoreCandidatesForUnusedTransportWhenBundling) {
Steve Anton7464fca2018-01-19 11:10:37 -0800576 // TODO(bugs.webrtc.org/8764): Re-enable when stats are supported with Unified
577 // Plan.
578 if (sdp_semantics_ == SdpSemantics::kUnifiedPlan) {
579 return;
580 }
581
Steve Anton6f25b092017-10-23 09:39:20 -0700582 const SocketAddress kAudioAddress1("1.1.1.1", 1111);
583 const SocketAddress kAudioAddress2("2.2.2.2", 2222);
584 const SocketAddress kVideoAddress("3.3.3.3", 3333);
585 const SocketAddress kCallerAddress("4.4.4.4", 0);
586 const SocketAddress kCalleeAddress("5.5.5.5", 0);
587
588 auto caller = CreatePeerConnectionWithAudioVideo();
589 auto callee = CreatePeerConnectionWithAudioVideo();
590
591 caller->network()->AddInterface(kCallerAddress);
592 callee->network()->AddInterface(kCalleeAddress);
593
594 RTCOfferAnswerOptions options;
595 options.use_rtp_mux = true;
596
597 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
598 ASSERT_TRUE(
599 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
600
601 // The way the *_WAIT checks work is they only wait if the condition fails,
602 // which does not help in the case where state is not changing. This is
603 // problematic in this test since we want to verify that adding a video
604 // candidate does _not_ change state. So we interleave candidates and assume
605 // that messages are executed in the order they were posted.
606
607 cricket::Candidate audio_candidate1 = CreateLocalUdpCandidate(kAudioAddress1);
608 ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate1,
609 cricket::MEDIA_TYPE_AUDIO));
610
611 cricket::Candidate video_candidate = CreateLocalUdpCandidate(kVideoAddress);
612 ASSERT_TRUE(caller->AddIceCandidateToMedia(&video_candidate,
613 cricket::MEDIA_TYPE_VIDEO));
614
615 cricket::Candidate audio_candidate2 = CreateLocalUdpCandidate(kAudioAddress2);
616 ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate2,
617 cricket::MEDIA_TYPE_AUDIO));
618
619 EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress1),
620 kDefaultTimeout);
621 EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress2),
622 kDefaultTimeout);
623 EXPECT_FALSE(caller->HasConnectionWithRemoteAddress(kVideoAddress));
624}
625
626// Test that the transport used by both audio and video is the transport
627// associated with the first MID in the answer BUNDLE group, even if it's in a
628// different order from the offer.
Steve Anton7464fca2018-01-19 11:10:37 -0800629TEST_P(PeerConnectionBundleTest, BundleOnFirstMidInAnswer) {
Steve Anton6f25b092017-10-23 09:39:20 -0700630 auto caller = CreatePeerConnectionWithAudioVideo();
631 auto callee = CreatePeerConnectionWithAudioVideo();
632
633 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
634
635 auto* old_video_transport = caller->video_rtp_transport_channel();
636
637 auto answer = callee->CreateAnswer();
638 auto* old_bundle_group =
639 answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
Steve Anton7464fca2018-01-19 11:10:37 -0800640 std::string first_mid = old_bundle_group->content_names()[0];
641 std::string second_mid = old_bundle_group->content_names()[1];
Steve Anton6f25b092017-10-23 09:39:20 -0700642 answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
643
644 cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
Steve Anton7464fca2018-01-19 11:10:37 -0800645 new_bundle_group.AddContentName(second_mid);
646 new_bundle_group.AddContentName(first_mid);
Steve Anton6f25b092017-10-23 09:39:20 -0700647 answer->description()->AddGroup(new_bundle_group);
648
649 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
650
651 EXPECT_EQ(old_video_transport, caller->video_rtp_transport_channel());
652 EXPECT_EQ(caller->voice_rtp_transport_channel(),
653 caller->video_rtp_transport_channel());
654}
655
Steve Anton7464fca2018-01-19 11:10:37 -0800656INSTANTIATE_TEST_CASE_P(PeerConnectionBundleTest,
657 PeerConnectionBundleTest,
658 Values(SdpSemantics::kPlanB,
659 SdpSemantics::kUnifiedPlan));
660
Steve Anton6f25b092017-10-23 09:39:20 -0700661} // namespace webrtc