1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cstdint>
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <ostream>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <tuple>
18*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker #include "api/audio/audio_mixer.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_encoder_factory.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/candidate.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/create_peerconnection_factory.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/jsep.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_receiver_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_sender_interface.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_transceiver_interface.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
34*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtc_stats.h"
35*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtc_stats_report.h"
36*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtcstats_objects.h"
37*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/builtin_video_decoder_factory.h"
38*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/builtin_video_encoder_factory.h"
39*d9f75844SAndroid Build Coastguard Worker #include "media/base/stream_params.h"
40*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_device/include/audio_device.h"
41*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing.h"
42*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
43*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port.h"
44*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port_allocator.h"
45*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_info.h"
46*d9f75844SAndroid Build Coastguard Worker #include "p2p/client/basic_port_allocator.h"
47*d9f75844SAndroid Build Coastguard Worker #include "pc/channel.h"
48*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection.h"
49*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection_proxy.h"
50*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection_wrapper.h"
51*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_transceiver.h"
52*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_transport_internal.h"
53*d9f75844SAndroid Build Coastguard Worker #include "pc/sdp_utils.h"
54*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h"
55*d9f75844SAndroid Build Coastguard Worker #include "pc/test/mock_peer_connection_observers.h"
56*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
57*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
58*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/net_helper.h"
59*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/network.h"
60*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate_generator.h"
61*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
62*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
63*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
64*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
65*d9f75844SAndroid Build Coastguard Worker #include "pc/test/android_test_initializer.h"
66*d9f75844SAndroid Build Coastguard Worker #endif
67*d9f75844SAndroid Build Coastguard Worker #include "pc/test/fake_audio_capture_module.h"
68*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/fake_network.h"
69*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
70*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
71*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
74*d9f75844SAndroid Build Coastguard Worker
75*d9f75844SAndroid Build Coastguard Worker using BundlePolicy = PeerConnectionInterface::BundlePolicy;
76*d9f75844SAndroid Build Coastguard Worker using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
77*d9f75844SAndroid Build Coastguard Worker using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
78*d9f75844SAndroid Build Coastguard Worker using RtcpMuxPolicy = PeerConnectionInterface::RtcpMuxPolicy;
79*d9f75844SAndroid Build Coastguard Worker using rtc::SocketAddress;
80*d9f75844SAndroid Build Coastguard Worker using ::testing::Combine;
81*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
82*d9f75844SAndroid Build Coastguard Worker using ::testing::UnorderedElementsAre;
83*d9f75844SAndroid Build Coastguard Worker using ::testing::Values;
84*d9f75844SAndroid Build Coastguard Worker
85*d9f75844SAndroid Build Coastguard Worker constexpr int kDefaultTimeout = 10000;
86*d9f75844SAndroid Build Coastguard Worker
87*d9f75844SAndroid Build Coastguard Worker // TODO(steveanton): These tests should be rewritten to use the standard
88*d9f75844SAndroid Build Coastguard Worker // RtpSenderInterface/DtlsTransportInterface objects once they're available in
89*d9f75844SAndroid Build Coastguard Worker // the API. The RtpSender can be used to determine which transport a given media
90*d9f75844SAndroid Build Coastguard Worker // will use: https://www.w3.org/TR/webrtc/#dom-rtcrtpsender-transport
91*d9f75844SAndroid Build Coastguard Worker // Should also be able to remove GetTransceiversForTesting at that point.
92*d9f75844SAndroid Build Coastguard Worker
93*d9f75844SAndroid Build Coastguard Worker class FakeNetworkManagerWithNoAnyNetwork : public rtc::FakeNetworkManager {
94*d9f75844SAndroid Build Coastguard Worker public:
GetAnyAddressNetworks()95*d9f75844SAndroid Build Coastguard Worker std::vector<const rtc::Network*> GetAnyAddressNetworks() override {
96*d9f75844SAndroid Build Coastguard Worker // This function allocates networks that are owned by the
97*d9f75844SAndroid Build Coastguard Worker // NetworkManager. But some tests assume that they can release
98*d9f75844SAndroid Build Coastguard Worker // all networks independent of the network manager.
99*d9f75844SAndroid Build Coastguard Worker // In order to prevent use-after-free issues, don't allow this
100*d9f75844SAndroid Build Coastguard Worker // function to have any effect when run in tests.
101*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "FakeNetworkManager::GetAnyAddressNetworks ignored";
102*d9f75844SAndroid Build Coastguard Worker return {};
103*d9f75844SAndroid Build Coastguard Worker }
104*d9f75844SAndroid Build Coastguard Worker };
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker class PeerConnectionWrapperForBundleTest : public PeerConnectionWrapper {
107*d9f75844SAndroid Build Coastguard Worker public:
108*d9f75844SAndroid Build Coastguard Worker using PeerConnectionWrapper::PeerConnectionWrapper;
109*d9f75844SAndroid Build Coastguard Worker
AddIceCandidateToMedia(cricket::Candidate * candidate,cricket::MediaType media_type)110*d9f75844SAndroid Build Coastguard Worker bool AddIceCandidateToMedia(cricket::Candidate* candidate,
111*d9f75844SAndroid Build Coastguard Worker cricket::MediaType media_type) {
112*d9f75844SAndroid Build Coastguard Worker auto* desc = pc()->remote_description()->description();
113*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < desc->contents().size(); i++) {
114*d9f75844SAndroid Build Coastguard Worker const auto& content = desc->contents()[i];
115*d9f75844SAndroid Build Coastguard Worker if (content.media_description()->type() == media_type) {
116*d9f75844SAndroid Build Coastguard Worker candidate->set_transport_name(content.name);
117*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<IceCandidateInterface> jsep_candidate =
118*d9f75844SAndroid Build Coastguard Worker CreateIceCandidate(content.name, i, *candidate);
119*d9f75844SAndroid Build Coastguard Worker return pc()->AddIceCandidate(jsep_candidate.get());
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker }
122*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
123*d9f75844SAndroid Build Coastguard Worker return false;
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker
voice_rtp_transport()126*d9f75844SAndroid Build Coastguard Worker RtpTransportInternal* voice_rtp_transport() {
127*d9f75844SAndroid Build Coastguard Worker return (voice_channel() ? voice_channel()->rtp_transport() : nullptr);
128*d9f75844SAndroid Build Coastguard Worker }
129*d9f75844SAndroid Build Coastguard Worker
voice_channel()130*d9f75844SAndroid Build Coastguard Worker cricket::VoiceChannel* voice_channel() {
131*d9f75844SAndroid Build Coastguard Worker auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
132*d9f75844SAndroid Build Coastguard Worker for (const auto& transceiver : transceivers) {
133*d9f75844SAndroid Build Coastguard Worker if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
134*d9f75844SAndroid Build Coastguard Worker return static_cast<cricket::VoiceChannel*>(
135*d9f75844SAndroid Build Coastguard Worker transceiver->internal()->channel());
136*d9f75844SAndroid Build Coastguard Worker }
137*d9f75844SAndroid Build Coastguard Worker }
138*d9f75844SAndroid Build Coastguard Worker return nullptr;
139*d9f75844SAndroid Build Coastguard Worker }
140*d9f75844SAndroid Build Coastguard Worker
video_rtp_transport()141*d9f75844SAndroid Build Coastguard Worker RtpTransportInternal* video_rtp_transport() {
142*d9f75844SAndroid Build Coastguard Worker return (video_channel() ? video_channel()->rtp_transport() : nullptr);
143*d9f75844SAndroid Build Coastguard Worker }
144*d9f75844SAndroid Build Coastguard Worker
video_channel()145*d9f75844SAndroid Build Coastguard Worker cricket::VideoChannel* video_channel() {
146*d9f75844SAndroid Build Coastguard Worker auto transceivers = GetInternalPeerConnection()->GetTransceiversInternal();
147*d9f75844SAndroid Build Coastguard Worker for (const auto& transceiver : transceivers) {
148*d9f75844SAndroid Build Coastguard Worker if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
149*d9f75844SAndroid Build Coastguard Worker return static_cast<cricket::VideoChannel*>(
150*d9f75844SAndroid Build Coastguard Worker transceiver->internal()->channel());
151*d9f75844SAndroid Build Coastguard Worker }
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker return nullptr;
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker
GetInternalPeerConnection()156*d9f75844SAndroid Build Coastguard Worker PeerConnection* GetInternalPeerConnection() {
157*d9f75844SAndroid Build Coastguard Worker auto* pci =
158*d9f75844SAndroid Build Coastguard Worker static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
159*d9f75844SAndroid Build Coastguard Worker pc());
160*d9f75844SAndroid Build Coastguard Worker return static_cast<PeerConnection*>(pci->internal());
161*d9f75844SAndroid Build Coastguard Worker }
162*d9f75844SAndroid Build Coastguard Worker
163*d9f75844SAndroid Build Coastguard Worker // Returns true if the stats indicate that an ICE connection is either in
164*d9f75844SAndroid Build Coastguard Worker // progress or established with the given remote address.
HasConnectionWithRemoteAddress(const SocketAddress & address)165*d9f75844SAndroid Build Coastguard Worker bool HasConnectionWithRemoteAddress(const SocketAddress& address) {
166*d9f75844SAndroid Build Coastguard Worker auto report = GetStats();
167*d9f75844SAndroid Build Coastguard Worker if (!report) {
168*d9f75844SAndroid Build Coastguard Worker return false;
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker std::string matching_candidate_id;
171*d9f75844SAndroid Build Coastguard Worker for (auto* ice_candidate_stats :
172*d9f75844SAndroid Build Coastguard Worker report->GetStatsOfType<RTCRemoteIceCandidateStats>()) {
173*d9f75844SAndroid Build Coastguard Worker if (*ice_candidate_stats->ip == address.HostAsURIString() &&
174*d9f75844SAndroid Build Coastguard Worker *ice_candidate_stats->port == address.port()) {
175*d9f75844SAndroid Build Coastguard Worker matching_candidate_id = ice_candidate_stats->id();
176*d9f75844SAndroid Build Coastguard Worker break;
177*d9f75844SAndroid Build Coastguard Worker }
178*d9f75844SAndroid Build Coastguard Worker }
179*d9f75844SAndroid Build Coastguard Worker if (matching_candidate_id.empty()) {
180*d9f75844SAndroid Build Coastguard Worker return false;
181*d9f75844SAndroid Build Coastguard Worker }
182*d9f75844SAndroid Build Coastguard Worker for (auto* pair_stats :
183*d9f75844SAndroid Build Coastguard Worker report->GetStatsOfType<RTCIceCandidatePairStats>()) {
184*d9f75844SAndroid Build Coastguard Worker if (*pair_stats->remote_candidate_id == matching_candidate_id) {
185*d9f75844SAndroid Build Coastguard Worker if (*pair_stats->state == RTCStatsIceCandidatePairState::kInProgress ||
186*d9f75844SAndroid Build Coastguard Worker *pair_stats->state == RTCStatsIceCandidatePairState::kSucceeded) {
187*d9f75844SAndroid Build Coastguard Worker return true;
188*d9f75844SAndroid Build Coastguard Worker }
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker return false;
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker
network()194*d9f75844SAndroid Build Coastguard Worker rtc::FakeNetworkManager* network() { return network_; }
195*d9f75844SAndroid Build Coastguard Worker
set_network(rtc::FakeNetworkManager * network)196*d9f75844SAndroid Build Coastguard Worker void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
197*d9f75844SAndroid Build Coastguard Worker
198*d9f75844SAndroid Build Coastguard Worker private:
199*d9f75844SAndroid Build Coastguard Worker rtc::FakeNetworkManager* network_;
200*d9f75844SAndroid Build Coastguard Worker };
201*d9f75844SAndroid Build Coastguard Worker
202*d9f75844SAndroid Build Coastguard Worker class PeerConnectionBundleBaseTest : public ::testing::Test {
203*d9f75844SAndroid Build Coastguard Worker protected:
204*d9f75844SAndroid Build Coastguard Worker typedef std::unique_ptr<PeerConnectionWrapperForBundleTest> WrapperPtr;
205*d9f75844SAndroid Build Coastguard Worker
PeerConnectionBundleBaseTest(SdpSemantics sdp_semantics)206*d9f75844SAndroid Build Coastguard Worker explicit PeerConnectionBundleBaseTest(SdpSemantics sdp_semantics)
207*d9f75844SAndroid Build Coastguard Worker : vss_(new rtc::VirtualSocketServer()),
208*d9f75844SAndroid Build Coastguard Worker main_(vss_.get()),
209*d9f75844SAndroid Build Coastguard Worker sdp_semantics_(sdp_semantics) {
210*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
211*d9f75844SAndroid Build Coastguard Worker InitializeAndroidObjects();
212*d9f75844SAndroid Build Coastguard Worker #endif
213*d9f75844SAndroid Build Coastguard Worker pc_factory_ = CreatePeerConnectionFactory(
214*d9f75844SAndroid Build Coastguard Worker rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
215*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
216*d9f75844SAndroid Build Coastguard Worker CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
217*d9f75844SAndroid Build Coastguard Worker CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
218*d9f75844SAndroid Build Coastguard Worker nullptr /* audio_mixer */, nullptr /* audio_processing */);
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker
CreatePeerConnection()221*d9f75844SAndroid Build Coastguard Worker WrapperPtr CreatePeerConnection() {
222*d9f75844SAndroid Build Coastguard Worker return CreatePeerConnection(RTCConfiguration());
223*d9f75844SAndroid Build Coastguard Worker }
224*d9f75844SAndroid Build Coastguard Worker
CreatePeerConnection(const RTCConfiguration & config)225*d9f75844SAndroid Build Coastguard Worker WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
226*d9f75844SAndroid Build Coastguard Worker auto* fake_network = NewFakeNetwork();
227*d9f75844SAndroid Build Coastguard Worker auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
228*d9f75844SAndroid Build Coastguard Worker fake_network,
229*d9f75844SAndroid Build Coastguard Worker std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
230*d9f75844SAndroid Build Coastguard Worker port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
231*d9f75844SAndroid Build Coastguard Worker cricket::PORTALLOCATOR_DISABLE_RELAY);
232*d9f75844SAndroid Build Coastguard Worker port_allocator->set_step_delay(cricket::kMinimumStepDelay);
233*d9f75844SAndroid Build Coastguard Worker auto observer = std::make_unique<MockPeerConnectionObserver>();
234*d9f75844SAndroid Build Coastguard Worker RTCConfiguration modified_config = config;
235*d9f75844SAndroid Build Coastguard Worker modified_config.sdp_semantics = sdp_semantics_;
236*d9f75844SAndroid Build Coastguard Worker PeerConnectionDependencies pc_dependencies(observer.get());
237*d9f75844SAndroid Build Coastguard Worker pc_dependencies.allocator = std::move(port_allocator);
238*d9f75844SAndroid Build Coastguard Worker auto result = pc_factory_->CreatePeerConnectionOrError(
239*d9f75844SAndroid Build Coastguard Worker modified_config, std::move(pc_dependencies));
240*d9f75844SAndroid Build Coastguard Worker if (!result.ok()) {
241*d9f75844SAndroid Build Coastguard Worker return nullptr;
242*d9f75844SAndroid Build Coastguard Worker }
243*d9f75844SAndroid Build Coastguard Worker
244*d9f75844SAndroid Build Coastguard Worker auto wrapper = std::make_unique<PeerConnectionWrapperForBundleTest>(
245*d9f75844SAndroid Build Coastguard Worker pc_factory_, result.MoveValue(), std::move(observer));
246*d9f75844SAndroid Build Coastguard Worker wrapper->set_network(fake_network);
247*d9f75844SAndroid Build Coastguard Worker return wrapper;
248*d9f75844SAndroid Build Coastguard Worker }
249*d9f75844SAndroid Build Coastguard Worker
250*d9f75844SAndroid Build Coastguard Worker // Accepts the same arguments as CreatePeerConnection and adds default audio
251*d9f75844SAndroid Build Coastguard Worker // and video tracks.
252*d9f75844SAndroid Build Coastguard Worker template <typename... Args>
CreatePeerConnectionWithAudioVideo(Args &&...args)253*d9f75844SAndroid Build Coastguard Worker WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
254*d9f75844SAndroid Build Coastguard Worker auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
255*d9f75844SAndroid Build Coastguard Worker if (!wrapper) {
256*d9f75844SAndroid Build Coastguard Worker return nullptr;
257*d9f75844SAndroid Build Coastguard Worker }
258*d9f75844SAndroid Build Coastguard Worker wrapper->AddAudioTrack("a");
259*d9f75844SAndroid Build Coastguard Worker wrapper->AddVideoTrack("v");
260*d9f75844SAndroid Build Coastguard Worker return wrapper;
261*d9f75844SAndroid Build Coastguard Worker }
262*d9f75844SAndroid Build Coastguard Worker
CreateLocalUdpCandidate(const rtc::SocketAddress & address)263*d9f75844SAndroid Build Coastguard Worker cricket::Candidate CreateLocalUdpCandidate(
264*d9f75844SAndroid Build Coastguard Worker const rtc::SocketAddress& address) {
265*d9f75844SAndroid Build Coastguard Worker cricket::Candidate candidate;
266*d9f75844SAndroid Build Coastguard Worker candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
267*d9f75844SAndroid Build Coastguard Worker candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
268*d9f75844SAndroid Build Coastguard Worker candidate.set_address(address);
269*d9f75844SAndroid Build Coastguard Worker candidate.set_type(cricket::LOCAL_PORT_TYPE);
270*d9f75844SAndroid Build Coastguard Worker return candidate;
271*d9f75844SAndroid Build Coastguard Worker }
272*d9f75844SAndroid Build Coastguard Worker
NewFakeNetwork()273*d9f75844SAndroid Build Coastguard Worker rtc::FakeNetworkManager* NewFakeNetwork() {
274*d9f75844SAndroid Build Coastguard Worker // The PeerConnection's port allocator is tied to the PeerConnection's
275*d9f75844SAndroid Build Coastguard Worker // lifetime and expects the underlying NetworkManager to outlive it. If
276*d9f75844SAndroid Build Coastguard Worker // PeerConnectionWrapper owned the NetworkManager, it would be destroyed
277*d9f75844SAndroid Build Coastguard Worker // before the PeerConnection (since subclass members are destroyed before
278*d9f75844SAndroid Build Coastguard Worker // base class members). Therefore, the test fixture will own all the fake
279*d9f75844SAndroid Build Coastguard Worker // networks even though tests should access the fake network through the
280*d9f75844SAndroid Build Coastguard Worker // PeerConnectionWrapper.
281*d9f75844SAndroid Build Coastguard Worker auto* fake_network = new FakeNetworkManagerWithNoAnyNetwork();
282*d9f75844SAndroid Build Coastguard Worker fake_networks_.emplace_back(fake_network);
283*d9f75844SAndroid Build Coastguard Worker return fake_network;
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker
286*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::VirtualSocketServer> vss_;
287*d9f75844SAndroid Build Coastguard Worker rtc::AutoSocketServerThread main_;
288*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
289*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
290*d9f75844SAndroid Build Coastguard Worker const SdpSemantics sdp_semantics_;
291*d9f75844SAndroid Build Coastguard Worker };
292*d9f75844SAndroid Build Coastguard Worker
293*d9f75844SAndroid Build Coastguard Worker class PeerConnectionBundleTest
294*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionBundleBaseTest,
295*d9f75844SAndroid Build Coastguard Worker public ::testing::WithParamInterface<SdpSemantics> {
296*d9f75844SAndroid Build Coastguard Worker protected:
PeerConnectionBundleTest()297*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleTest() : PeerConnectionBundleBaseTest(GetParam()) {}
298*d9f75844SAndroid Build Coastguard Worker };
299*d9f75844SAndroid Build Coastguard Worker
300*d9f75844SAndroid Build Coastguard Worker class PeerConnectionBundleTestUnifiedPlan
301*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionBundleBaseTest {
302*d9f75844SAndroid Build Coastguard Worker protected:
PeerConnectionBundleTestUnifiedPlan()303*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleTestUnifiedPlan()
304*d9f75844SAndroid Build Coastguard Worker : PeerConnectionBundleBaseTest(SdpSemantics::kUnifiedPlan) {}
305*d9f75844SAndroid Build Coastguard Worker };
306*d9f75844SAndroid Build Coastguard Worker
RemoveRtcpMux()307*d9f75844SAndroid Build Coastguard Worker SdpContentMutator RemoveRtcpMux() {
308*d9f75844SAndroid Build Coastguard Worker return [](cricket::ContentInfo* content, cricket::TransportInfo* transport) {
309*d9f75844SAndroid Build Coastguard Worker content->media_description()->set_rtcp_mux(false);
310*d9f75844SAndroid Build Coastguard Worker };
311*d9f75844SAndroid Build Coastguard Worker }
312*d9f75844SAndroid Build Coastguard Worker
GetCandidateComponents(const std::vector<IceCandidateInterface * > candidates)313*d9f75844SAndroid Build Coastguard Worker std::vector<int> GetCandidateComponents(
314*d9f75844SAndroid Build Coastguard Worker const std::vector<IceCandidateInterface*> candidates) {
315*d9f75844SAndroid Build Coastguard Worker std::vector<int> components;
316*d9f75844SAndroid Build Coastguard Worker components.reserve(candidates.size());
317*d9f75844SAndroid Build Coastguard Worker for (auto* candidate : candidates) {
318*d9f75844SAndroid Build Coastguard Worker components.push_back(candidate->candidate().component());
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker return components;
321*d9f75844SAndroid Build Coastguard Worker }
322*d9f75844SAndroid Build Coastguard Worker
323*d9f75844SAndroid Build Coastguard Worker // Test that there are 2 local UDP candidates (1 RTP and 1 RTCP candidate) for
324*d9f75844SAndroid Build Coastguard Worker // each media section when disabling bundling and disabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,TwoCandidatesForEachTransportWhenNoBundleNoRtcpMux)325*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
326*d9f75844SAndroid Build Coastguard Worker TwoCandidatesForEachTransportWhenNoBundleNoRtcpMux) {
327*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCallerAddress("1.1.1.1", 0);
328*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCalleeAddress("2.2.2.2", 0);
329*d9f75844SAndroid Build Coastguard Worker
330*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
331*d9f75844SAndroid Build Coastguard Worker config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate;
332*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
333*d9f75844SAndroid Build Coastguard Worker caller->network()->AddInterface(kCallerAddress);
334*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo(config);
335*d9f75844SAndroid Build Coastguard Worker callee->network()->AddInterface(kCalleeAddress);
336*d9f75844SAndroid Build Coastguard Worker
337*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
338*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options_no_bundle;
339*d9f75844SAndroid Build Coastguard Worker options_no_bundle.use_rtp_mux = false;
340*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer(options_no_bundle);
341*d9f75844SAndroid Build Coastguard Worker SdpContentsForEach(RemoveRtcpMux(), answer->description());
342*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
343*d9f75844SAndroid Build Coastguard Worker callee->SetLocalDescription(CloneSessionDescription(answer.get())));
344*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
345*d9f75844SAndroid Build Coastguard Worker
346*d9f75844SAndroid Build Coastguard Worker // Check that caller has separate RTP and RTCP candidates for each media.
347*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
348*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
349*d9f75844SAndroid Build Coastguard Worker GetCandidateComponents(caller->observer()->GetCandidatesByMline(0)),
350*d9f75844SAndroid Build Coastguard Worker UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
351*d9f75844SAndroid Build Coastguard Worker cricket::ICE_CANDIDATE_COMPONENT_RTCP));
352*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
353*d9f75844SAndroid Build Coastguard Worker GetCandidateComponents(caller->observer()->GetCandidatesByMline(1)),
354*d9f75844SAndroid Build Coastguard Worker UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
355*d9f75844SAndroid Build Coastguard Worker cricket::ICE_CANDIDATE_COMPONENT_RTCP));
356*d9f75844SAndroid Build Coastguard Worker
357*d9f75844SAndroid Build Coastguard Worker // Check that callee has separate RTP and RTCP candidates for each media.
358*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kDefaultTimeout);
359*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
360*d9f75844SAndroid Build Coastguard Worker GetCandidateComponents(callee->observer()->GetCandidatesByMline(0)),
361*d9f75844SAndroid Build Coastguard Worker UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
362*d9f75844SAndroid Build Coastguard Worker cricket::ICE_CANDIDATE_COMPONENT_RTCP));
363*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(
364*d9f75844SAndroid Build Coastguard Worker GetCandidateComponents(callee->observer()->GetCandidatesByMline(1)),
365*d9f75844SAndroid Build Coastguard Worker UnorderedElementsAre(cricket::ICE_CANDIDATE_COMPONENT_RTP,
366*d9f75844SAndroid Build Coastguard Worker cricket::ICE_CANDIDATE_COMPONENT_RTCP));
367*d9f75844SAndroid Build Coastguard Worker }
368*d9f75844SAndroid Build Coastguard Worker
369*d9f75844SAndroid Build Coastguard Worker // Test that there is 1 local UDP candidate for both RTP and RTCP for each media
370*d9f75844SAndroid Build Coastguard Worker // section when disabling bundle but enabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,OneCandidateForEachTransportWhenNoBundleButRtcpMux)371*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
372*d9f75844SAndroid Build Coastguard Worker OneCandidateForEachTransportWhenNoBundleButRtcpMux) {
373*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCallerAddress("1.1.1.1", 0);
374*d9f75844SAndroid Build Coastguard Worker
375*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
376*d9f75844SAndroid Build Coastguard Worker caller->network()->AddInterface(kCallerAddress);
377*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
378*d9f75844SAndroid Build Coastguard Worker
379*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
380*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options_no_bundle;
381*d9f75844SAndroid Build Coastguard Worker options_no_bundle.use_rtp_mux = false;
382*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
383*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswer(options_no_bundle)));
384*d9f75844SAndroid Build Coastguard Worker
385*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
386*d9f75844SAndroid Build Coastguard Worker
387*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
388*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(1).size());
389*d9f75844SAndroid Build Coastguard Worker }
390*d9f75844SAndroid Build Coastguard Worker
391*d9f75844SAndroid Build Coastguard Worker // Test that there is 1 local UDP candidate in only the first media section when
392*d9f75844SAndroid Build Coastguard Worker // bundling and enabling RTCP multiplexing.
TEST_P(PeerConnectionBundleTest,OneCandidateOnlyOnFirstTransportWhenBundleAndRtcpMux)393*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
394*d9f75844SAndroid Build Coastguard Worker OneCandidateOnlyOnFirstTransportWhenBundleAndRtcpMux) {
395*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCallerAddress("1.1.1.1", 0);
396*d9f75844SAndroid Build Coastguard Worker
397*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
398*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
399*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
400*d9f75844SAndroid Build Coastguard Worker caller->network()->AddInterface(kCallerAddress);
401*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo(config);
402*d9f75844SAndroid Build Coastguard Worker
403*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
404*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
405*d9f75844SAndroid Build Coastguard Worker
406*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kDefaultTimeout);
407*d9f75844SAndroid Build Coastguard Worker
408*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, caller->observer()->GetCandidatesByMline(0).size());
409*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(0u, caller->observer()->GetCandidatesByMline(1).size());
410*d9f75844SAndroid Build Coastguard Worker }
411*d9f75844SAndroid Build Coastguard Worker
412*d9f75844SAndroid Build Coastguard Worker // It will fail if the offerer uses the mux-BUNDLE policy but the answerer
413*d9f75844SAndroid Build Coastguard Worker // doesn't support BUNDLE.
TEST_P(PeerConnectionBundleTest,MaxBundleNotSupportedInAnswer)414*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, MaxBundleNotSupportedInAnswer) {
415*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
416*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
417*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
418*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
419*d9f75844SAndroid Build Coastguard Worker
420*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
421*d9f75844SAndroid Build Coastguard Worker bool equal_before =
422*d9f75844SAndroid Build Coastguard Worker (caller->voice_rtp_transport() == caller->video_rtp_transport());
423*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(true, equal_before);
424*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
425*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = false;
426*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(
427*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
428*d9f75844SAndroid Build Coastguard Worker }
429*d9f75844SAndroid Build Coastguard Worker
430*d9f75844SAndroid Build Coastguard Worker // The following parameterized test verifies that an offer/answer with varying
431*d9f75844SAndroid Build Coastguard Worker // bundle policies and either bundle in the answer or not will produce the
432*d9f75844SAndroid Build Coastguard Worker // expected RTP transports for audio and video. In particular, for bundling we
433*d9f75844SAndroid Build Coastguard Worker // care about whether they are separate transports or the same.
434*d9f75844SAndroid Build Coastguard Worker
435*d9f75844SAndroid Build Coastguard Worker enum class BundleIncluded { kBundleInAnswer, kBundleNotInAnswer };
operator <<(std::ostream & out,BundleIncluded value)436*d9f75844SAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& out, BundleIncluded value) {
437*d9f75844SAndroid Build Coastguard Worker switch (value) {
438*d9f75844SAndroid Build Coastguard Worker case BundleIncluded::kBundleInAnswer:
439*d9f75844SAndroid Build Coastguard Worker return out << "bundle in answer";
440*d9f75844SAndroid Build Coastguard Worker case BundleIncluded::kBundleNotInAnswer:
441*d9f75844SAndroid Build Coastguard Worker return out << "bundle not in answer";
442*d9f75844SAndroid Build Coastguard Worker }
443*d9f75844SAndroid Build Coastguard Worker return out << "unknown";
444*d9f75844SAndroid Build Coastguard Worker }
445*d9f75844SAndroid Build Coastguard Worker
446*d9f75844SAndroid Build Coastguard Worker class PeerConnectionBundleMatrixTest
447*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionBundleBaseTest,
448*d9f75844SAndroid Build Coastguard Worker public ::testing::WithParamInterface<
449*d9f75844SAndroid Build Coastguard Worker std::tuple<SdpSemantics,
450*d9f75844SAndroid Build Coastguard Worker std::tuple<BundlePolicy, BundleIncluded, bool, bool>>> {
451*d9f75844SAndroid Build Coastguard Worker protected:
PeerConnectionBundleMatrixTest()452*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleMatrixTest()
453*d9f75844SAndroid Build Coastguard Worker : PeerConnectionBundleBaseTest(std::get<0>(GetParam())) {
454*d9f75844SAndroid Build Coastguard Worker auto param = std::get<1>(GetParam());
455*d9f75844SAndroid Build Coastguard Worker bundle_policy_ = std::get<0>(param);
456*d9f75844SAndroid Build Coastguard Worker bundle_included_ = std::get<1>(param);
457*d9f75844SAndroid Build Coastguard Worker expected_same_before_ = std::get<2>(param);
458*d9f75844SAndroid Build Coastguard Worker expected_same_after_ = std::get<3>(param);
459*d9f75844SAndroid Build Coastguard Worker }
460*d9f75844SAndroid Build Coastguard Worker
461*d9f75844SAndroid Build Coastguard Worker PeerConnectionInterface::BundlePolicy bundle_policy_;
462*d9f75844SAndroid Build Coastguard Worker BundleIncluded bundle_included_;
463*d9f75844SAndroid Build Coastguard Worker bool expected_same_before_;
464*d9f75844SAndroid Build Coastguard Worker bool expected_same_after_;
465*d9f75844SAndroid Build Coastguard Worker };
466*d9f75844SAndroid Build Coastguard Worker
TEST_P(PeerConnectionBundleMatrixTest,VerifyTransportsBeforeAndAfterSettingRemoteAnswer)467*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleMatrixTest,
468*d9f75844SAndroid Build Coastguard Worker VerifyTransportsBeforeAndAfterSettingRemoteAnswer) {
469*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
470*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = bundle_policy_;
471*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
472*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
473*d9f75844SAndroid Build Coastguard Worker
474*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
475*d9f75844SAndroid Build Coastguard Worker bool equal_before =
476*d9f75844SAndroid Build Coastguard Worker (caller->voice_rtp_transport() == caller->video_rtp_transport());
477*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_same_before_, equal_before);
478*d9f75844SAndroid Build Coastguard Worker
479*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
480*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = (bundle_included_ == BundleIncluded::kBundleInAnswer);
481*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
482*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
483*d9f75844SAndroid Build Coastguard Worker bool equal_after =
484*d9f75844SAndroid Build Coastguard Worker (caller->voice_rtp_transport() == caller->video_rtp_transport());
485*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(expected_same_after_, equal_after);
486*d9f75844SAndroid Build Coastguard Worker }
487*d9f75844SAndroid Build Coastguard Worker
488*d9f75844SAndroid Build Coastguard Worker // The max-bundle policy means we should anticipate bundling being negotiated,
489*d9f75844SAndroid Build Coastguard Worker // and multiplex audio/video from the start.
490*d9f75844SAndroid Build Coastguard Worker // For all other policies, bundling should only be enabled if negotiated by the
491*d9f75844SAndroid Build Coastguard Worker // answer.
492*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
493*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleTest,
494*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleMatrixTest,
495*d9f75844SAndroid Build Coastguard Worker Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
496*d9f75844SAndroid Build Coastguard Worker Values(std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
497*d9f75844SAndroid Build Coastguard Worker BundleIncluded::kBundleInAnswer,
498*d9f75844SAndroid Build Coastguard Worker false,
499*d9f75844SAndroid Build Coastguard Worker true),
500*d9f75844SAndroid Build Coastguard Worker std::make_tuple(BundlePolicy::kBundlePolicyBalanced,
501*d9f75844SAndroid Build Coastguard Worker BundleIncluded::kBundleNotInAnswer,
502*d9f75844SAndroid Build Coastguard Worker false,
503*d9f75844SAndroid Build Coastguard Worker false),
504*d9f75844SAndroid Build Coastguard Worker std::make_tuple(BundlePolicy::kBundlePolicyMaxBundle,
505*d9f75844SAndroid Build Coastguard Worker BundleIncluded::kBundleInAnswer,
506*d9f75844SAndroid Build Coastguard Worker true,
507*d9f75844SAndroid Build Coastguard Worker true),
508*d9f75844SAndroid Build Coastguard Worker std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
509*d9f75844SAndroid Build Coastguard Worker BundleIncluded::kBundleInAnswer,
510*d9f75844SAndroid Build Coastguard Worker false,
511*d9f75844SAndroid Build Coastguard Worker true),
512*d9f75844SAndroid Build Coastguard Worker std::make_tuple(BundlePolicy::kBundlePolicyMaxCompat,
513*d9f75844SAndroid Build Coastguard Worker BundleIncluded::kBundleNotInAnswer,
514*d9f75844SAndroid Build Coastguard Worker false,
515*d9f75844SAndroid Build Coastguard Worker false))));
516*d9f75844SAndroid Build Coastguard Worker
517*d9f75844SAndroid Build Coastguard Worker // Test that the audio/video transports on the callee side are the same before
518*d9f75844SAndroid Build Coastguard Worker // and after setting a local answer when max BUNDLE is enabled and an offer with
519*d9f75844SAndroid Build Coastguard Worker // BUNDLE is received.
TEST_P(PeerConnectionBundleTest,TransportsSameForMaxBundleWithBundleInRemoteOffer)520*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
521*d9f75844SAndroid Build Coastguard Worker TransportsSameForMaxBundleWithBundleInRemoteOffer) {
522*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
523*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
524*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
525*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo(config);
526*d9f75844SAndroid Build Coastguard Worker
527*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options_with_bundle;
528*d9f75844SAndroid Build Coastguard Worker options_with_bundle.use_rtp_mux = true;
529*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(
530*d9f75844SAndroid Build Coastguard Worker caller->CreateOfferAndSetAsLocal(options_with_bundle)));
531*d9f75844SAndroid Build Coastguard Worker
532*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee->voice_rtp_transport(), callee->video_rtp_transport());
533*d9f75844SAndroid Build Coastguard Worker
534*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
535*d9f75844SAndroid Build Coastguard Worker
536*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee->voice_rtp_transport(), callee->video_rtp_transport());
537*d9f75844SAndroid Build Coastguard Worker }
538*d9f75844SAndroid Build Coastguard Worker
TEST_P(PeerConnectionBundleTest,FailToSetRemoteOfferWithNoBundleWhenBundlePolicyMaxBundle)539*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
540*d9f75844SAndroid Build Coastguard Worker FailToSetRemoteOfferWithNoBundleWhenBundlePolicyMaxBundle) {
541*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
542*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
543*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
544*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo(config);
545*d9f75844SAndroid Build Coastguard Worker
546*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options_no_bundle;
547*d9f75844SAndroid Build Coastguard Worker options_no_bundle.use_rtp_mux = false;
548*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee->SetRemoteDescription(
549*d9f75844SAndroid Build Coastguard Worker caller->CreateOfferAndSetAsLocal(options_no_bundle)));
550*d9f75844SAndroid Build Coastguard Worker }
551*d9f75844SAndroid Build Coastguard Worker
552*d9f75844SAndroid Build Coastguard Worker // Test that if the media section which has the bundled transport is rejected,
553*d9f75844SAndroid Build Coastguard Worker // then the peers still connect and the bundled transport switches to the other
554*d9f75844SAndroid Build Coastguard Worker // media section.
555*d9f75844SAndroid Build Coastguard Worker // Note: This is currently failing because of the following bug:
556*d9f75844SAndroid Build Coastguard Worker // https://bugs.chromium.org/p/webrtc/issues/detail?id=6280
TEST_P(PeerConnectionBundleTest,DISABLED_SuccessfullyNegotiateMaxBundleIfBundleTransportMediaRejected)557*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
558*d9f75844SAndroid Build Coastguard Worker DISABLED_SuccessfullyNegotiateMaxBundleIfBundleTransportMediaRejected) {
559*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
560*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
561*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
562*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnection();
563*d9f75844SAndroid Build Coastguard Worker callee->AddVideoTrack("v");
564*d9f75844SAndroid Build Coastguard Worker
565*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
566*d9f75844SAndroid Build Coastguard Worker
567*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
568*d9f75844SAndroid Build Coastguard Worker options.offer_to_receive_audio = 0;
569*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
570*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
571*d9f75844SAndroid Build Coastguard Worker
572*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->voice_rtp_transport());
573*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->video_rtp_transport());
574*d9f75844SAndroid Build Coastguard Worker }
575*d9f75844SAndroid Build Coastguard Worker
576*d9f75844SAndroid Build Coastguard Worker // When requiring RTCP multiplexing, the PeerConnection never makes RTCP
577*d9f75844SAndroid Build Coastguard Worker // transport channels.
TEST_P(PeerConnectionBundleTest,NeverCreateRtcpTransportWithRtcpMuxRequired)578*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, NeverCreateRtcpTransportWithRtcpMuxRequired) {
579*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
580*d9f75844SAndroid Build Coastguard Worker config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyRequire;
581*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
582*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
583*d9f75844SAndroid Build Coastguard Worker
584*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
585*d9f75844SAndroid Build Coastguard Worker
586*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->voice_rtp_transport()->rtcp_mux_enabled());
587*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->video_rtp_transport()->rtcp_mux_enabled());
588*d9f75844SAndroid Build Coastguard Worker
589*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
590*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
591*d9f75844SAndroid Build Coastguard Worker
592*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->voice_rtp_transport()->rtcp_mux_enabled());
593*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->video_rtp_transport()->rtcp_mux_enabled());
594*d9f75844SAndroid Build Coastguard Worker }
595*d9f75844SAndroid Build Coastguard Worker
596*d9f75844SAndroid Build Coastguard Worker // When negotiating RTCP multiplexing, the PeerConnection makes RTCP transports
597*d9f75844SAndroid Build Coastguard Worker // when the offer is sent, but will destroy them once the remote answer is set.
TEST_P(PeerConnectionBundleTest,CreateRtcpTransportOnlyBeforeAnswerWithRtcpMuxNegotiate)598*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
599*d9f75844SAndroid Build Coastguard Worker CreateRtcpTransportOnlyBeforeAnswerWithRtcpMuxNegotiate) {
600*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
601*d9f75844SAndroid Build Coastguard Worker config.rtcp_mux_policy = RtcpMuxPolicy::kRtcpMuxPolicyNegotiate;
602*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
603*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
604*d9f75844SAndroid Build Coastguard Worker
605*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
606*d9f75844SAndroid Build Coastguard Worker
607*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->voice_rtp_transport()->rtcp_mux_enabled());
608*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->video_rtp_transport()->rtcp_mux_enabled());
609*d9f75844SAndroid Build Coastguard Worker
610*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
611*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
612*d9f75844SAndroid Build Coastguard Worker
613*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->voice_rtp_transport()->rtcp_mux_enabled());
614*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->video_rtp_transport()->rtcp_mux_enabled());
615*d9f75844SAndroid Build Coastguard Worker }
616*d9f75844SAndroid Build Coastguard Worker
TEST_P(PeerConnectionBundleTest,FailToSetDescriptionWithBundleAndNoRtcpMux)617*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, FailToSetDescriptionWithBundleAndNoRtcpMux) {
618*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
619*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
620*d9f75844SAndroid Build Coastguard Worker
621*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
622*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = true;
623*d9f75844SAndroid Build Coastguard Worker
624*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer(options);
625*d9f75844SAndroid Build Coastguard Worker SdpContentsForEach(RemoveRtcpMux(), offer->description());
626*d9f75844SAndroid Build Coastguard Worker
627*d9f75844SAndroid Build Coastguard Worker std::string error;
628*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->SetLocalDescription(CloneSessionDescription(offer.get()),
629*d9f75844SAndroid Build Coastguard Worker &error));
630*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
631*d9f75844SAndroid Build Coastguard Worker "Failed to set local offer sdp: rtcp-mux must be enabled when BUNDLE is "
632*d9f75844SAndroid Build Coastguard Worker "enabled.",
633*d9f75844SAndroid Build Coastguard Worker error);
634*d9f75844SAndroid Build Coastguard Worker
635*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
636*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(
637*d9f75844SAndroid Build Coastguard Worker "Failed to set remote offer sdp: rtcp-mux must be enabled when BUNDLE is "
638*d9f75844SAndroid Build Coastguard Worker "enabled.",
639*d9f75844SAndroid Build Coastguard Worker error);
640*d9f75844SAndroid Build Coastguard Worker }
641*d9f75844SAndroid Build Coastguard Worker
642*d9f75844SAndroid Build Coastguard Worker // Test that candidates sent to the "video" transport do not get pushed down to
643*d9f75844SAndroid Build Coastguard Worker // the "audio" transport channel when bundling.
TEST_P(PeerConnectionBundleTest,IgnoreCandidatesForUnusedTransportWhenBundling)644*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
645*d9f75844SAndroid Build Coastguard Worker IgnoreCandidatesForUnusedTransportWhenBundling) {
646*d9f75844SAndroid Build Coastguard Worker const SocketAddress kAudioAddress1("1.1.1.1", 1111);
647*d9f75844SAndroid Build Coastguard Worker const SocketAddress kAudioAddress2("2.2.2.2", 2222);
648*d9f75844SAndroid Build Coastguard Worker const SocketAddress kVideoAddress("3.3.3.3", 3333);
649*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCallerAddress("4.4.4.4", 0);
650*d9f75844SAndroid Build Coastguard Worker const SocketAddress kCalleeAddress("5.5.5.5", 0);
651*d9f75844SAndroid Build Coastguard Worker
652*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
653*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
654*d9f75844SAndroid Build Coastguard Worker
655*d9f75844SAndroid Build Coastguard Worker caller->network()->AddInterface(kCallerAddress);
656*d9f75844SAndroid Build Coastguard Worker callee->network()->AddInterface(kCalleeAddress);
657*d9f75844SAndroid Build Coastguard Worker
658*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
659*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = true;
660*d9f75844SAndroid Build Coastguard Worker
661*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
662*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
663*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(options)));
664*d9f75844SAndroid Build Coastguard Worker
665*d9f75844SAndroid Build Coastguard Worker // The way the *_WAIT checks work is they only wait if the condition fails,
666*d9f75844SAndroid Build Coastguard Worker // which does not help in the case where state is not changing. This is
667*d9f75844SAndroid Build Coastguard Worker // problematic in this test since we want to verify that adding a video
668*d9f75844SAndroid Build Coastguard Worker // candidate does _not_ change state. So we interleave candidates and assume
669*d9f75844SAndroid Build Coastguard Worker // that messages are executed in the order they were posted.
670*d9f75844SAndroid Build Coastguard Worker
671*d9f75844SAndroid Build Coastguard Worker cricket::Candidate audio_candidate1 = CreateLocalUdpCandidate(kAudioAddress1);
672*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate1,
673*d9f75844SAndroid Build Coastguard Worker cricket::MEDIA_TYPE_AUDIO));
674*d9f75844SAndroid Build Coastguard Worker
675*d9f75844SAndroid Build Coastguard Worker cricket::Candidate video_candidate = CreateLocalUdpCandidate(kVideoAddress);
676*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->AddIceCandidateToMedia(&video_candidate,
677*d9f75844SAndroid Build Coastguard Worker cricket::MEDIA_TYPE_VIDEO));
678*d9f75844SAndroid Build Coastguard Worker
679*d9f75844SAndroid Build Coastguard Worker cricket::Candidate audio_candidate2 = CreateLocalUdpCandidate(kAudioAddress2);
680*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->AddIceCandidateToMedia(&audio_candidate2,
681*d9f75844SAndroid Build Coastguard Worker cricket::MEDIA_TYPE_AUDIO));
682*d9f75844SAndroid Build Coastguard Worker
683*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress1),
684*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
685*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller->HasConnectionWithRemoteAddress(kAudioAddress2),
686*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
687*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->HasConnectionWithRemoteAddress(kVideoAddress));
688*d9f75844SAndroid Build Coastguard Worker }
689*d9f75844SAndroid Build Coastguard Worker
690*d9f75844SAndroid Build Coastguard Worker // Test that the transport used by both audio and video is the transport
691*d9f75844SAndroid Build Coastguard Worker // associated with the first MID in the answer BUNDLE group, even if it's in a
692*d9f75844SAndroid Build Coastguard Worker // different order from the offer.
TEST_P(PeerConnectionBundleTest,BundleOnFirstMidInAnswer)693*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, BundleOnFirstMidInAnswer) {
694*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
695*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
696*d9f75844SAndroid Build Coastguard Worker
697*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
698*d9f75844SAndroid Build Coastguard Worker
699*d9f75844SAndroid Build Coastguard Worker auto* old_video_transport = caller->video_rtp_transport();
700*d9f75844SAndroid Build Coastguard Worker
701*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer();
702*d9f75844SAndroid Build Coastguard Worker auto* old_bundle_group =
703*d9f75844SAndroid Build Coastguard Worker answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
704*d9f75844SAndroid Build Coastguard Worker std::string first_mid = old_bundle_group->content_names()[0];
705*d9f75844SAndroid Build Coastguard Worker std::string second_mid = old_bundle_group->content_names()[1];
706*d9f75844SAndroid Build Coastguard Worker answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
707*d9f75844SAndroid Build Coastguard Worker
708*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
709*d9f75844SAndroid Build Coastguard Worker new_bundle_group.AddContentName(second_mid);
710*d9f75844SAndroid Build Coastguard Worker new_bundle_group.AddContentName(first_mid);
711*d9f75844SAndroid Build Coastguard Worker answer->description()->AddGroup(new_bundle_group);
712*d9f75844SAndroid Build Coastguard Worker
713*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
714*d9f75844SAndroid Build Coastguard Worker
715*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(old_video_transport, caller->video_rtp_transport());
716*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller->voice_rtp_transport(), caller->video_rtp_transport());
717*d9f75844SAndroid Build Coastguard Worker }
718*d9f75844SAndroid Build Coastguard Worker
719*d9f75844SAndroid Build Coastguard Worker // This tests that applying description with conflicted RTP demuxing criteria
720*d9f75844SAndroid Build Coastguard Worker // will fail.
TEST_P(PeerConnectionBundleTest,ApplyDescriptionWithConflictedDemuxCriteriaFail)721*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest,
722*d9f75844SAndroid Build Coastguard Worker ApplyDescriptionWithConflictedDemuxCriteriaFail) {
723*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
724*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
725*d9f75844SAndroid Build Coastguard Worker
726*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
727*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = false;
728*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer(options);
729*d9f75844SAndroid Build Coastguard Worker // Modified the SDP to make two m= sections have the same SSRC.
730*d9f75844SAndroid Build Coastguard Worker ASSERT_GE(offer->description()->contents().size(), 2U);
731*d9f75844SAndroid Build Coastguard Worker offer->description()
732*d9f75844SAndroid Build Coastguard Worker ->contents()[0]
733*d9f75844SAndroid Build Coastguard Worker .media_description()
734*d9f75844SAndroid Build Coastguard Worker ->mutable_streams()[0]
735*d9f75844SAndroid Build Coastguard Worker .ssrcs[0] = 1111222;
736*d9f75844SAndroid Build Coastguard Worker offer->description()
737*d9f75844SAndroid Build Coastguard Worker ->contents()[1]
738*d9f75844SAndroid Build Coastguard Worker .media_description()
739*d9f75844SAndroid Build Coastguard Worker ->mutable_streams()[0]
740*d9f75844SAndroid Build Coastguard Worker .ssrcs[0] = 1111222;
741*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
742*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
743*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
744*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->CreateAnswerAndSetAsLocal(options));
745*d9f75844SAndroid Build Coastguard Worker
746*d9f75844SAndroid Build Coastguard Worker // Enable BUNDLE in subsequent offer/answer exchange and two m= sections are
747*d9f75844SAndroid Build Coastguard Worker // expectd to use one RtpTransport underneath.
748*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = true;
749*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
750*d9f75844SAndroid Build Coastguard Worker callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
751*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer(options);
752*d9f75844SAndroid Build Coastguard Worker // When BUNDLE is enabled, applying the description is expected to fail
753*d9f75844SAndroid Build Coastguard Worker // because the demuxing criteria is conflicted.
754*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
755*d9f75844SAndroid Build Coastguard Worker }
756*d9f75844SAndroid Build Coastguard Worker
757*d9f75844SAndroid Build Coastguard Worker // This tests that changing the pre-negotiated BUNDLE tag is not supported.
TEST_P(PeerConnectionBundleTest,RejectDescriptionChangingBundleTag)758*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, RejectDescriptionChangingBundleTag) {
759*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
760*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
761*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
762*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo(config);
763*d9f75844SAndroid Build Coastguard Worker
764*d9f75844SAndroid Build Coastguard Worker RTCOfferAnswerOptions options;
765*d9f75844SAndroid Build Coastguard Worker options.use_rtp_mux = true;
766*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOfferAndSetAsLocal(options);
767*d9f75844SAndroid Build Coastguard Worker
768*d9f75844SAndroid Build Coastguard Worker // Create a new bundle-group with different bundled_mid.
769*d9f75844SAndroid Build Coastguard Worker auto* old_bundle_group =
770*d9f75844SAndroid Build Coastguard Worker offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
771*d9f75844SAndroid Build Coastguard Worker std::string first_mid = old_bundle_group->content_names()[0];
772*d9f75844SAndroid Build Coastguard Worker std::string second_mid = old_bundle_group->content_names()[1];
773*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
774*d9f75844SAndroid Build Coastguard Worker new_bundle_group.AddContentName(second_mid);
775*d9f75844SAndroid Build Coastguard Worker
776*d9f75844SAndroid Build Coastguard Worker auto re_offer = CloneSessionDescription(offer.get());
777*d9f75844SAndroid Build Coastguard Worker callee->SetRemoteDescription(std::move(offer));
778*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer(options);
779*d9f75844SAndroid Build Coastguard Worker // Reject the first MID.
780*d9f75844SAndroid Build Coastguard Worker answer->description()->contents()[0].rejected = true;
781*d9f75844SAndroid Build Coastguard Worker // Remove the first MID from the bundle group.
782*d9f75844SAndroid Build Coastguard Worker answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
783*d9f75844SAndroid Build Coastguard Worker answer->description()->AddGroup(new_bundle_group);
784*d9f75844SAndroid Build Coastguard Worker // The answer is expected to be rejected.
785*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
786*d9f75844SAndroid Build Coastguard Worker
787*d9f75844SAndroid Build Coastguard Worker // Do the same thing for re-offer.
788*d9f75844SAndroid Build Coastguard Worker re_offer->description()->contents()[0].rejected = true;
789*d9f75844SAndroid Build Coastguard Worker re_offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
790*d9f75844SAndroid Build Coastguard Worker re_offer->description()->AddGroup(new_bundle_group);
791*d9f75844SAndroid Build Coastguard Worker // The re-offer is expected to be rejected.
792*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller->SetLocalDescription(std::move(re_offer)));
793*d9f75844SAndroid Build Coastguard Worker }
794*d9f75844SAndroid Build Coastguard Worker
795*d9f75844SAndroid Build Coastguard Worker // This tests that removing contents from BUNDLE group and reject the whole
796*d9f75844SAndroid Build Coastguard Worker // BUNDLE group could work. This is a regression test for
797*d9f75844SAndroid Build Coastguard Worker // (https://bugs.chromium.org/p/chromium/issues/detail?id=827917)
798*d9f75844SAndroid Build Coastguard Worker #ifdef HAVE_SCTP
TEST_P(PeerConnectionBundleTest,RemovingContentAndRejectBundleGroup)799*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, RemovingContentAndRejectBundleGroup) {
800*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
801*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = BundlePolicy::kBundlePolicyMaxBundle;
802*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo(config);
803*d9f75844SAndroid Build Coastguard Worker caller->CreateDataChannel("dc");
804*d9f75844SAndroid Build Coastguard Worker
805*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOfferAndSetAsLocal();
806*d9f75844SAndroid Build Coastguard Worker auto re_offer = CloneSessionDescription(offer.get());
807*d9f75844SAndroid Build Coastguard Worker
808*d9f75844SAndroid Build Coastguard Worker // Removing the second MID from the BUNDLE group.
809*d9f75844SAndroid Build Coastguard Worker auto* old_bundle_group =
810*d9f75844SAndroid Build Coastguard Worker offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
811*d9f75844SAndroid Build Coastguard Worker std::string first_mid = old_bundle_group->content_names()[0];
812*d9f75844SAndroid Build Coastguard Worker std::string third_mid = old_bundle_group->content_names()[2];
813*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup new_bundle_group(cricket::GROUP_TYPE_BUNDLE);
814*d9f75844SAndroid Build Coastguard Worker new_bundle_group.AddContentName(first_mid);
815*d9f75844SAndroid Build Coastguard Worker new_bundle_group.AddContentName(third_mid);
816*d9f75844SAndroid Build Coastguard Worker
817*d9f75844SAndroid Build Coastguard Worker // Reject the entire new bundle group.
818*d9f75844SAndroid Build Coastguard Worker re_offer->description()->contents()[0].rejected = true;
819*d9f75844SAndroid Build Coastguard Worker re_offer->description()->contents()[2].rejected = true;
820*d9f75844SAndroid Build Coastguard Worker re_offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
821*d9f75844SAndroid Build Coastguard Worker re_offer->description()->AddGroup(new_bundle_group);
822*d9f75844SAndroid Build Coastguard Worker
823*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->SetLocalDescription(std::move(re_offer)));
824*d9f75844SAndroid Build Coastguard Worker }
825*d9f75844SAndroid Build Coastguard Worker #endif
826*d9f75844SAndroid Build Coastguard Worker
827*d9f75844SAndroid Build Coastguard Worker // This tests that the BUNDLE group in answer should be a subset of the offered
828*d9f75844SAndroid Build Coastguard Worker // group.
TEST_P(PeerConnectionBundleTest,AddContentToBundleGroupInAnswerNotSupported)829*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, AddContentToBundleGroupInAnswerNotSupported) {
830*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
831*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
832*d9f75844SAndroid Build Coastguard Worker
833*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer();
834*d9f75844SAndroid Build Coastguard Worker std::string first_mid = offer->description()->contents()[0].name;
835*d9f75844SAndroid Build Coastguard Worker std::string second_mid = offer->description()->contents()[1].name;
836*d9f75844SAndroid Build Coastguard Worker
837*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
838*d9f75844SAndroid Build Coastguard Worker bundle_group.AddContentName(first_mid);
839*d9f75844SAndroid Build Coastguard Worker offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
840*d9f75844SAndroid Build Coastguard Worker offer->description()->AddGroup(bundle_group);
841*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
842*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
843*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
844*d9f75844SAndroid Build Coastguard Worker
845*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer();
846*d9f75844SAndroid Build Coastguard Worker bundle_group.AddContentName(second_mid);
847*d9f75844SAndroid Build Coastguard Worker answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
848*d9f75844SAndroid Build Coastguard Worker answer->description()->AddGroup(bundle_group);
849*d9f75844SAndroid Build Coastguard Worker
850*d9f75844SAndroid Build Coastguard Worker // The answer is expected to be rejected because second mid is not in the
851*d9f75844SAndroid Build Coastguard Worker // offered BUNDLE group.
852*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee->SetLocalDescription(std::move(answer)));
853*d9f75844SAndroid Build Coastguard Worker }
854*d9f75844SAndroid Build Coastguard Worker
855*d9f75844SAndroid Build Coastguard Worker // This tests that the BUNDLE group with non-existing MID should be rejectd.
TEST_P(PeerConnectionBundleTest,RejectBundleGroupWithNonExistingMid)856*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, RejectBundleGroupWithNonExistingMid) {
857*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
858*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
859*d9f75844SAndroid Build Coastguard Worker
860*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer();
861*d9f75844SAndroid Build Coastguard Worker auto invalid_bundle_group =
862*d9f75844SAndroid Build Coastguard Worker *offer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
863*d9f75844SAndroid Build Coastguard Worker invalid_bundle_group.AddContentName("non-existing-MID");
864*d9f75844SAndroid Build Coastguard Worker offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
865*d9f75844SAndroid Build Coastguard Worker offer->description()->AddGroup(invalid_bundle_group);
866*d9f75844SAndroid Build Coastguard Worker
867*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(
868*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
869*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
870*d9f75844SAndroid Build Coastguard Worker }
871*d9f75844SAndroid Build Coastguard Worker
872*d9f75844SAndroid Build Coastguard Worker // This tests that an answer shouldn't be able to remove an m= section from an
873*d9f75844SAndroid Build Coastguard Worker // established group without rejecting it.
TEST_P(PeerConnectionBundleTest,RemoveContentFromBundleGroup)874*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionBundleTest, RemoveContentFromBundleGroup) {
875*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
876*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnectionWithAudioVideo();
877*d9f75844SAndroid Build Coastguard Worker
878*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
879*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
880*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
881*d9f75844SAndroid Build Coastguard Worker
882*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
883*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer();
884*d9f75844SAndroid Build Coastguard Worker std::string second_mid = answer->description()->contents()[1].name;
885*d9f75844SAndroid Build Coastguard Worker
886*d9f75844SAndroid Build Coastguard Worker auto invalid_bundle_group =
887*d9f75844SAndroid Build Coastguard Worker *answer->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
888*d9f75844SAndroid Build Coastguard Worker invalid_bundle_group.RemoveContentName(second_mid);
889*d9f75844SAndroid Build Coastguard Worker answer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
890*d9f75844SAndroid Build Coastguard Worker answer->description()->AddGroup(invalid_bundle_group);
891*d9f75844SAndroid Build Coastguard Worker
892*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(
893*d9f75844SAndroid Build Coastguard Worker callee->SetLocalDescription(CloneSessionDescription(answer.get())));
894*d9f75844SAndroid Build Coastguard Worker }
895*d9f75844SAndroid Build Coastguard Worker
896*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(PeerConnectionBundleTest,
897*d9f75844SAndroid Build Coastguard Worker PeerConnectionBundleTest,
898*d9f75844SAndroid Build Coastguard Worker Values(SdpSemantics::kPlanB_DEPRECATED,
899*d9f75844SAndroid Build Coastguard Worker SdpSemantics::kUnifiedPlan));
900*d9f75844SAndroid Build Coastguard Worker
901*d9f75844SAndroid Build Coastguard Worker // According to RFC5888, if an endpoint understands the semantics of an
902*d9f75844SAndroid Build Coastguard Worker // "a=group", it MUST return an answer with that group. So, an empty BUNDLE
903*d9f75844SAndroid Build Coastguard Worker // group is valid when the answerer rejects all m= sections (by stopping all
904*d9f75844SAndroid Build Coastguard Worker // transceivers), meaning there's nothing to bundle.
905*d9f75844SAndroid Build Coastguard Worker //
906*d9f75844SAndroid Build Coastguard Worker // Only writing this test for Unified Plan mode, since there's no way to reject
907*d9f75844SAndroid Build Coastguard Worker // m= sections in answers for Plan B without SDP munging.
TEST_F(PeerConnectionBundleTestUnifiedPlan,EmptyBundleGroupCreatedInAnswerWhenAppropriate)908*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionBundleTestUnifiedPlan,
909*d9f75844SAndroid Build Coastguard Worker EmptyBundleGroupCreatedInAnswerWhenAppropriate) {
910*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnectionWithAudioVideo();
911*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnection();
912*d9f75844SAndroid Build Coastguard Worker
913*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
914*d9f75844SAndroid Build Coastguard Worker
915*d9f75844SAndroid Build Coastguard Worker // Stop all transceivers, causing all m= sections to be rejected.
916*d9f75844SAndroid Build Coastguard Worker for (const auto& transceiver : callee->pc()->GetTransceivers()) {
917*d9f75844SAndroid Build Coastguard Worker transceiver->StopInternal();
918*d9f75844SAndroid Build Coastguard Worker }
919*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
920*d9f75844SAndroid Build Coastguard Worker caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
921*d9f75844SAndroid Build Coastguard Worker
922*d9f75844SAndroid Build Coastguard Worker // Verify that the answer actually contained an empty bundle group.
923*d9f75844SAndroid Build Coastguard Worker const SessionDescriptionInterface* desc = callee->pc()->local_description();
924*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, desc);
925*d9f75844SAndroid Build Coastguard Worker const cricket::ContentGroup* bundle_group =
926*d9f75844SAndroid Build Coastguard Worker desc->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
927*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, bundle_group);
928*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(bundle_group->content_names().empty());
929*d9f75844SAndroid Build Coastguard Worker }
930*d9f75844SAndroid Build Coastguard Worker
TEST_F(PeerConnectionBundleTestUnifiedPlan,MultipleBundleGroups)931*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionBundleTestUnifiedPlan, MultipleBundleGroups) {
932*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnection();
933*d9f75844SAndroid Build Coastguard Worker caller->AddAudioTrack("0_audio");
934*d9f75844SAndroid Build Coastguard Worker caller->AddAudioTrack("1_audio");
935*d9f75844SAndroid Build Coastguard Worker caller->AddVideoTrack("2_audio");
936*d9f75844SAndroid Build Coastguard Worker caller->AddVideoTrack("3_audio");
937*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnection();
938*d9f75844SAndroid Build Coastguard Worker
939*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
940*d9f75844SAndroid Build Coastguard Worker // Modify the GROUP to have two BUNDLEs. We know that the MIDs will be 0,1,2,4
941*d9f75844SAndroid Build Coastguard Worker // because our implementation has predictable MIDs.
942*d9f75844SAndroid Build Coastguard Worker offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
943*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup bundle_group1(cricket::GROUP_TYPE_BUNDLE);
944*d9f75844SAndroid Build Coastguard Worker bundle_group1.AddContentName("0");
945*d9f75844SAndroid Build Coastguard Worker bundle_group1.AddContentName("1");
946*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup bundle_group2(cricket::GROUP_TYPE_BUNDLE);
947*d9f75844SAndroid Build Coastguard Worker bundle_group2.AddContentName("2");
948*d9f75844SAndroid Build Coastguard Worker bundle_group2.AddContentName("3");
949*d9f75844SAndroid Build Coastguard Worker offer->description()->AddGroup(bundle_group1);
950*d9f75844SAndroid Build Coastguard Worker offer->description()->AddGroup(bundle_group2);
951*d9f75844SAndroid Build Coastguard Worker
952*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
953*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
954*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
955*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer();
956*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
957*d9f75844SAndroid Build Coastguard Worker callee->SetLocalDescription(CloneSessionDescription(answer.get())));
958*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
959*d9f75844SAndroid Build Coastguard Worker
960*d9f75844SAndroid Build Coastguard Worker // Verify bundling on sender side.
961*d9f75844SAndroid Build Coastguard Worker auto senders = caller->pc()->GetSenders();
962*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(senders.size(), 4u);
963*d9f75844SAndroid Build Coastguard Worker auto sender0_transport = senders[0]->dtls_transport();
964*d9f75844SAndroid Build Coastguard Worker auto sender1_transport = senders[1]->dtls_transport();
965*d9f75844SAndroid Build Coastguard Worker auto sender2_transport = senders[2]->dtls_transport();
966*d9f75844SAndroid Build Coastguard Worker auto sender3_transport = senders[3]->dtls_transport();
967*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sender0_transport, sender1_transport);
968*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sender2_transport, sender3_transport);
969*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(sender0_transport, sender2_transport);
970*d9f75844SAndroid Build Coastguard Worker
971*d9f75844SAndroid Build Coastguard Worker // Verify bundling on receiver side.
972*d9f75844SAndroid Build Coastguard Worker auto receivers = callee->pc()->GetReceivers();
973*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(receivers.size(), 4u);
974*d9f75844SAndroid Build Coastguard Worker auto receiver0_transport = receivers[0]->dtls_transport();
975*d9f75844SAndroid Build Coastguard Worker auto receiver1_transport = receivers[1]->dtls_transport();
976*d9f75844SAndroid Build Coastguard Worker auto receiver2_transport = receivers[2]->dtls_transport();
977*d9f75844SAndroid Build Coastguard Worker auto receiver3_transport = receivers[3]->dtls_transport();
978*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(receiver0_transport, receiver1_transport);
979*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(receiver2_transport, receiver3_transport);
980*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(receiver0_transport, receiver2_transport);
981*d9f75844SAndroid Build Coastguard Worker }
982*d9f75844SAndroid Build Coastguard Worker
983*d9f75844SAndroid Build Coastguard Worker // Test that, with the "max-compat" bundle policy, it's possible to add an m=
984*d9f75844SAndroid Build Coastguard Worker // section that's not part of an existing bundle group.
TEST_F(PeerConnectionBundleTestUnifiedPlan,AddNonBundledSection)985*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionBundleTestUnifiedPlan, AddNonBundledSection) {
986*d9f75844SAndroid Build Coastguard Worker RTCConfiguration config;
987*d9f75844SAndroid Build Coastguard Worker config.bundle_policy = PeerConnectionInterface::kBundlePolicyMaxCompat;
988*d9f75844SAndroid Build Coastguard Worker auto caller = CreatePeerConnection(config);
989*d9f75844SAndroid Build Coastguard Worker caller->AddAudioTrack("0_audio");
990*d9f75844SAndroid Build Coastguard Worker caller->AddAudioTrack("1_audio");
991*d9f75844SAndroid Build Coastguard Worker auto callee = CreatePeerConnection(config);
992*d9f75844SAndroid Build Coastguard Worker
993*d9f75844SAndroid Build Coastguard Worker // Establish an existing BUNDLE group.
994*d9f75844SAndroid Build Coastguard Worker auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
995*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
996*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
997*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
998*d9f75844SAndroid Build Coastguard Worker auto answer = callee->CreateAnswer();
999*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
1000*d9f75844SAndroid Build Coastguard Worker callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1001*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1002*d9f75844SAndroid Build Coastguard Worker
1003*d9f75844SAndroid Build Coastguard Worker // Add a track but munge SDP so it's not part of the bundle group.
1004*d9f75844SAndroid Build Coastguard Worker caller->AddAudioTrack("3_audio");
1005*d9f75844SAndroid Build Coastguard Worker offer = caller->CreateOffer(RTCOfferAnswerOptions());
1006*d9f75844SAndroid Build Coastguard Worker offer->description()->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1007*d9f75844SAndroid Build Coastguard Worker cricket::ContentGroup bundle_group(cricket::GROUP_TYPE_BUNDLE);
1008*d9f75844SAndroid Build Coastguard Worker bundle_group.AddContentName("0");
1009*d9f75844SAndroid Build Coastguard Worker bundle_group.AddContentName("1");
1010*d9f75844SAndroid Build Coastguard Worker offer->description()->AddGroup(bundle_group);
1011*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
1012*d9f75844SAndroid Build Coastguard Worker caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1013*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1014*d9f75844SAndroid Build Coastguard Worker answer = callee->CreateAnswer();
1015*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(
1016*d9f75844SAndroid Build Coastguard Worker callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1017*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1018*d9f75844SAndroid Build Coastguard Worker
1019*d9f75844SAndroid Build Coastguard Worker // Verify bundling on the sender side.
1020*d9f75844SAndroid Build Coastguard Worker auto senders = caller->pc()->GetSenders();
1021*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(senders.size(), 3u);
1022*d9f75844SAndroid Build Coastguard Worker auto sender0_transport = senders[0]->dtls_transport();
1023*d9f75844SAndroid Build Coastguard Worker auto sender1_transport = senders[1]->dtls_transport();
1024*d9f75844SAndroid Build Coastguard Worker auto sender2_transport = senders[2]->dtls_transport();
1025*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sender0_transport, sender1_transport);
1026*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(sender0_transport, sender2_transport);
1027*d9f75844SAndroid Build Coastguard Worker
1028*d9f75844SAndroid Build Coastguard Worker // Verify bundling on receiver side.
1029*d9f75844SAndroid Build Coastguard Worker auto receivers = callee->pc()->GetReceivers();
1030*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(receivers.size(), 3u);
1031*d9f75844SAndroid Build Coastguard Worker auto receiver0_transport = receivers[0]->dtls_transport();
1032*d9f75844SAndroid Build Coastguard Worker auto receiver1_transport = receivers[1]->dtls_transport();
1033*d9f75844SAndroid Build Coastguard Worker auto receiver2_transport = receivers[2]->dtls_transport();
1034*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(receiver0_transport, receiver1_transport);
1035*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(receiver0_transport, receiver2_transport);
1036*d9f75844SAndroid Build Coastguard Worker }
1037*d9f75844SAndroid Build Coastguard Worker
1038*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
1039