xref: /aosp_15_r20/external/webrtc/pc/peer_connection_ice_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 #include <stdint.h>
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <memory>
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <tuple>
17*d9f75844SAndroid Build Coastguard Worker #include <type_traits>
18*d9f75844SAndroid Build Coastguard Worker #include <utility>
19*d9f75844SAndroid Build Coastguard Worker #include <vector>
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/audio/audio_mixer.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/candidate.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/ice_transport_interface.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/jsep.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/media_types.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/rtc_error.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
30*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_device/include/audio_device.h"
31*d9f75844SAndroid Build Coastguard Worker #include "modules/audio_processing/include/audio_processing.h"
32*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/fake_port_allocator.h"
33*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/ice_transport_internal.h"
34*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
35*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port.h"
36*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port_allocator.h"
37*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_description.h"
38*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_info.h"
39*d9f75844SAndroid Build Coastguard Worker #include "p2p/client/basic_port_allocator.h"
40*d9f75844SAndroid Build Coastguard Worker #include "pc/channel_interface.h"
41*d9f75844SAndroid Build Coastguard Worker #include "pc/dtls_transport.h"
42*d9f75844SAndroid Build Coastguard Worker #include "pc/media_session.h"
43*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection.h"
44*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection_wrapper.h"
45*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_transceiver.h"
46*d9f75844SAndroid Build Coastguard Worker #include "pc/sdp_utils.h"
47*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h"
48*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
49*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/internal/default_socket_server.h"
50*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ip_address.h"
51*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
52*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/net_helper.h"
53*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rtc_certificate_generator.h"
54*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/socket_address.h"
55*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
56*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
57*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
58*d9f75844SAndroid Build Coastguard Worker #include "pc/test/android_test_initializer.h"
59*d9f75844SAndroid Build Coastguard Worker #endif
60*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_decoder_factory.h"
61*d9f75844SAndroid Build Coastguard Worker #include "api/audio_codecs/builtin_audio_encoder_factory.h"
62*d9f75844SAndroid Build Coastguard Worker #include "api/create_peerconnection_factory.h"
63*d9f75844SAndroid Build Coastguard Worker #include "api/uma_metrics.h"
64*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/builtin_video_decoder_factory.h"
65*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/builtin_video_encoder_factory.h"
66*d9f75844SAndroid Build Coastguard Worker #include "pc/peer_connection_proxy.h"
67*d9f75844SAndroid Build Coastguard Worker #include "pc/test/fake_audio_capture_module.h"
68*d9f75844SAndroid Build Coastguard Worker #include "pc/test/mock_peer_connection_observers.h"
69*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/fake_network.h"
70*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
71*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
72*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
73*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/metrics.h"
74*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
75*d9f75844SAndroid Build Coastguard Worker 
76*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
79*d9f75844SAndroid Build Coastguard Worker using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
80*d9f75844SAndroid Build Coastguard Worker using rtc::SocketAddress;
81*d9f75844SAndroid Build Coastguard Worker using ::testing::Combine;
82*d9f75844SAndroid Build Coastguard Worker using ::testing::ElementsAre;
83*d9f75844SAndroid Build Coastguard Worker using ::testing::Pair;
84*d9f75844SAndroid Build Coastguard Worker using ::testing::Values;
85*d9f75844SAndroid Build Coastguard Worker 
86*d9f75844SAndroid Build Coastguard Worker constexpr int kIceCandidatesTimeout = 10000;
87*d9f75844SAndroid Build Coastguard Worker constexpr int64_t kWaitTimeout = 10000;
88*d9f75844SAndroid Build Coastguard Worker constexpr uint64_t kTiebreakerDefault = 44444;
89*d9f75844SAndroid Build Coastguard Worker 
90*d9f75844SAndroid Build Coastguard Worker class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
91*d9f75844SAndroid Build Coastguard Worker  public:
92*d9f75844SAndroid Build Coastguard Worker   using PeerConnectionWrapper::PeerConnectionWrapper;
93*d9f75844SAndroid Build Coastguard Worker 
CreateJsepCandidateForFirstTransport(cricket::Candidate * candidate)94*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> CreateJsepCandidateForFirstTransport(
95*d9f75844SAndroid Build Coastguard Worker       cricket::Candidate* candidate) {
96*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(pc()->remote_description());
97*d9f75844SAndroid Build Coastguard Worker     const auto* desc = pc()->remote_description()->description();
98*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(desc->contents().size() > 0);
99*d9f75844SAndroid Build Coastguard Worker     const auto& first_content = desc->contents()[0];
100*d9f75844SAndroid Build Coastguard Worker     candidate->set_transport_name(first_content.name);
101*d9f75844SAndroid Build Coastguard Worker     return CreateIceCandidate(first_content.name, -1, *candidate);
102*d9f75844SAndroid Build Coastguard Worker   }
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker   // Adds a new ICE candidate to the first transport.
AddIceCandidate(cricket::Candidate * candidate)105*d9f75844SAndroid Build Coastguard Worker   bool AddIceCandidate(cricket::Candidate* candidate) {
106*d9f75844SAndroid Build Coastguard Worker     return pc()->AddIceCandidate(
107*d9f75844SAndroid Build Coastguard Worker         CreateJsepCandidateForFirstTransport(candidate).get());
108*d9f75844SAndroid Build Coastguard Worker   }
109*d9f75844SAndroid Build Coastguard Worker 
110*d9f75844SAndroid Build Coastguard Worker   // Returns ICE candidates from the remote session description.
111*d9f75844SAndroid Build Coastguard Worker   std::vector<const IceCandidateInterface*>
GetIceCandidatesFromRemoteDescription()112*d9f75844SAndroid Build Coastguard Worker   GetIceCandidatesFromRemoteDescription() {
113*d9f75844SAndroid Build Coastguard Worker     const SessionDescriptionInterface* sdesc = pc()->remote_description();
114*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(sdesc);
115*d9f75844SAndroid Build Coastguard Worker     std::vector<const IceCandidateInterface*> candidates;
116*d9f75844SAndroid Build Coastguard Worker     for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
117*d9f75844SAndroid Build Coastguard Worker          mline_index++) {
118*d9f75844SAndroid Build Coastguard Worker       const auto* candidate_collection = sdesc->candidates(mline_index);
119*d9f75844SAndroid Build Coastguard Worker       for (size_t i = 0; i < candidate_collection->count(); i++) {
120*d9f75844SAndroid Build Coastguard Worker         candidates.push_back(candidate_collection->at(i));
121*d9f75844SAndroid Build Coastguard Worker       }
122*d9f75844SAndroid Build Coastguard Worker     }
123*d9f75844SAndroid Build Coastguard Worker     return candidates;
124*d9f75844SAndroid Build Coastguard Worker   }
125*d9f75844SAndroid Build Coastguard Worker 
network()126*d9f75844SAndroid Build Coastguard Worker   rtc::FakeNetworkManager* network() { return network_; }
127*d9f75844SAndroid Build Coastguard Worker 
set_network(rtc::FakeNetworkManager * network)128*d9f75844SAndroid Build Coastguard Worker   void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker   // The port allocator used by this PC.
131*d9f75844SAndroid Build Coastguard Worker   cricket::PortAllocator* port_allocator_;
132*d9f75844SAndroid Build Coastguard Worker 
133*d9f75844SAndroid Build Coastguard Worker  private:
134*d9f75844SAndroid Build Coastguard Worker   rtc::FakeNetworkManager* network_;
135*d9f75844SAndroid Build Coastguard Worker };
136*d9f75844SAndroid Build Coastguard Worker 
137*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceBaseTest : public ::testing::Test {
138*d9f75844SAndroid Build Coastguard Worker  protected:
139*d9f75844SAndroid Build Coastguard Worker   typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
140*d9f75844SAndroid Build Coastguard Worker 
PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)141*d9f75844SAndroid Build Coastguard Worker   explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
142*d9f75844SAndroid Build Coastguard Worker       : vss_(new rtc::VirtualSocketServer()),
143*d9f75844SAndroid Build Coastguard Worker         main_(vss_.get()),
144*d9f75844SAndroid Build Coastguard Worker         sdp_semantics_(sdp_semantics) {
145*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_ANDROID
146*d9f75844SAndroid Build Coastguard Worker     InitializeAndroidObjects();
147*d9f75844SAndroid Build Coastguard Worker #endif
148*d9f75844SAndroid Build Coastguard Worker     pc_factory_ = CreatePeerConnectionFactory(
149*d9f75844SAndroid Build Coastguard Worker         rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
150*d9f75844SAndroid Build Coastguard Worker         rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
151*d9f75844SAndroid Build Coastguard Worker         CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
152*d9f75844SAndroid Build Coastguard Worker         CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
153*d9f75844SAndroid Build Coastguard Worker         nullptr /* audio_mixer */, nullptr /* audio_processing */);
154*d9f75844SAndroid Build Coastguard Worker   }
155*d9f75844SAndroid Build Coastguard Worker 
CreatePeerConnection()156*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection() {
157*d9f75844SAndroid Build Coastguard Worker     return CreatePeerConnection(RTCConfiguration());
158*d9f75844SAndroid Build Coastguard Worker   }
159*d9f75844SAndroid Build Coastguard Worker 
CreatePeerConnection(const RTCConfiguration & config)160*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
161*d9f75844SAndroid Build Coastguard Worker     auto* fake_network = NewFakeNetwork();
162*d9f75844SAndroid Build Coastguard Worker     auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
163*d9f75844SAndroid Build Coastguard Worker         fake_network,
164*d9f75844SAndroid Build Coastguard Worker         std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
165*d9f75844SAndroid Build Coastguard Worker     port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
166*d9f75844SAndroid Build Coastguard Worker                               cricket::PORTALLOCATOR_DISABLE_RELAY);
167*d9f75844SAndroid Build Coastguard Worker     port_allocator->set_step_delay(cricket::kMinimumStepDelay);
168*d9f75844SAndroid Build Coastguard Worker     RTCConfiguration modified_config = config;
169*d9f75844SAndroid Build Coastguard Worker     modified_config.sdp_semantics = sdp_semantics_;
170*d9f75844SAndroid Build Coastguard Worker     auto observer = std::make_unique<MockPeerConnectionObserver>();
171*d9f75844SAndroid Build Coastguard Worker     auto port_allocator_copy = port_allocator.get();
172*d9f75844SAndroid Build Coastguard Worker     PeerConnectionDependencies pc_dependencies(observer.get());
173*d9f75844SAndroid Build Coastguard Worker     pc_dependencies.allocator = std::move(port_allocator);
174*d9f75844SAndroid Build Coastguard Worker     auto result = pc_factory_->CreatePeerConnectionOrError(
175*d9f75844SAndroid Build Coastguard Worker         modified_config, std::move(pc_dependencies));
176*d9f75844SAndroid Build Coastguard Worker     if (!result.ok()) {
177*d9f75844SAndroid Build Coastguard Worker       return nullptr;
178*d9f75844SAndroid Build Coastguard Worker     }
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker     observer->SetPeerConnectionInterface(result.value().get());
181*d9f75844SAndroid Build Coastguard Worker     auto wrapper = std::make_unique<PeerConnectionWrapperForIceTest>(
182*d9f75844SAndroid Build Coastguard Worker         pc_factory_, result.MoveValue(), std::move(observer));
183*d9f75844SAndroid Build Coastguard Worker     wrapper->set_network(fake_network);
184*d9f75844SAndroid Build Coastguard Worker     wrapper->port_allocator_ = port_allocator_copy;
185*d9f75844SAndroid Build Coastguard Worker     return wrapper;
186*d9f75844SAndroid Build Coastguard Worker   }
187*d9f75844SAndroid Build Coastguard Worker 
188*d9f75844SAndroid Build Coastguard Worker   // Accepts the same arguments as CreatePeerConnection and adds default audio
189*d9f75844SAndroid Build Coastguard Worker   // and video tracks.
190*d9f75844SAndroid Build Coastguard Worker   template <typename... Args>
CreatePeerConnectionWithAudioVideo(Args &&...args)191*d9f75844SAndroid Build Coastguard Worker   WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
192*d9f75844SAndroid Build Coastguard Worker     auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
193*d9f75844SAndroid Build Coastguard Worker     if (!wrapper) {
194*d9f75844SAndroid Build Coastguard Worker       return nullptr;
195*d9f75844SAndroid Build Coastguard Worker     }
196*d9f75844SAndroid Build Coastguard Worker     wrapper->AddAudioTrack("a");
197*d9f75844SAndroid Build Coastguard Worker     wrapper->AddVideoTrack("v");
198*d9f75844SAndroid Build Coastguard Worker     return wrapper;
199*d9f75844SAndroid Build Coastguard Worker   }
200*d9f75844SAndroid Build Coastguard Worker 
CreateLocalUdpCandidate(const rtc::SocketAddress & address)201*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate CreateLocalUdpCandidate(
202*d9f75844SAndroid Build Coastguard Worker       const rtc::SocketAddress& address) {
203*d9f75844SAndroid Build Coastguard Worker     cricket::Candidate candidate;
204*d9f75844SAndroid Build Coastguard Worker     candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
205*d9f75844SAndroid Build Coastguard Worker     candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
206*d9f75844SAndroid Build Coastguard Worker     candidate.set_address(address);
207*d9f75844SAndroid Build Coastguard Worker     candidate.set_type(cricket::LOCAL_PORT_TYPE);
208*d9f75844SAndroid Build Coastguard Worker     return candidate;
209*d9f75844SAndroid Build Coastguard Worker   }
210*d9f75844SAndroid Build Coastguard Worker 
211*d9f75844SAndroid Build Coastguard Worker   // Remove all ICE ufrag/pwd lines from the given session description.
RemoveIceUfragPwd(SessionDescriptionInterface * sdesc)212*d9f75844SAndroid Build Coastguard Worker   void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
213*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(sdesc, "", "");
214*d9f75844SAndroid Build Coastguard Worker   }
215*d9f75844SAndroid Build Coastguard Worker 
216*d9f75844SAndroid Build Coastguard Worker   // Sets all ICE ufrag/pwds on the given session description.
SetIceUfragPwd(SessionDescriptionInterface * sdesc,const std::string & ufrag,const std::string & pwd)217*d9f75844SAndroid Build Coastguard Worker   void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
218*d9f75844SAndroid Build Coastguard Worker                       const std::string& ufrag,
219*d9f75844SAndroid Build Coastguard Worker                       const std::string& pwd) {
220*d9f75844SAndroid Build Coastguard Worker     auto* desc = sdesc->description();
221*d9f75844SAndroid Build Coastguard Worker     for (const auto& content : desc->contents()) {
222*d9f75844SAndroid Build Coastguard Worker       auto* transport_info = desc->GetTransportInfoByName(content.name);
223*d9f75844SAndroid Build Coastguard Worker       transport_info->description.ice_ufrag = ufrag;
224*d9f75844SAndroid Build Coastguard Worker       transport_info->description.ice_pwd = pwd;
225*d9f75844SAndroid Build Coastguard Worker     }
226*d9f75844SAndroid Build Coastguard Worker   }
227*d9f75844SAndroid Build Coastguard Worker 
228*d9f75844SAndroid Build Coastguard Worker   // Set ICE mode on the given session description.
SetIceMode(SessionDescriptionInterface * sdesc,const cricket::IceMode ice_mode)229*d9f75844SAndroid Build Coastguard Worker   void SetIceMode(SessionDescriptionInterface* sdesc,
230*d9f75844SAndroid Build Coastguard Worker                   const cricket::IceMode ice_mode) {
231*d9f75844SAndroid Build Coastguard Worker     auto* desc = sdesc->description();
232*d9f75844SAndroid Build Coastguard Worker     for (const auto& content : desc->contents()) {
233*d9f75844SAndroid Build Coastguard Worker       auto* transport_info = desc->GetTransportInfoByName(content.name);
234*d9f75844SAndroid Build Coastguard Worker       transport_info->description.ice_mode = ice_mode;
235*d9f75844SAndroid Build Coastguard Worker     }
236*d9f75844SAndroid Build Coastguard Worker   }
237*d9f75844SAndroid Build Coastguard Worker 
GetFirstTransportDescription(SessionDescriptionInterface * sdesc)238*d9f75844SAndroid Build Coastguard Worker   cricket::TransportDescription* GetFirstTransportDescription(
239*d9f75844SAndroid Build Coastguard Worker       SessionDescriptionInterface* sdesc) {
240*d9f75844SAndroid Build Coastguard Worker     auto* desc = sdesc->description();
241*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(desc->contents().size() > 0);
242*d9f75844SAndroid Build Coastguard Worker     auto* transport_info =
243*d9f75844SAndroid Build Coastguard Worker         desc->GetTransportInfoByName(desc->contents()[0].name);
244*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(transport_info);
245*d9f75844SAndroid Build Coastguard Worker     return &transport_info->description;
246*d9f75844SAndroid Build Coastguard Worker   }
247*d9f75844SAndroid Build Coastguard Worker 
GetFirstTransportDescription(const SessionDescriptionInterface * sdesc)248*d9f75844SAndroid Build Coastguard Worker   const cricket::TransportDescription* GetFirstTransportDescription(
249*d9f75844SAndroid Build Coastguard Worker       const SessionDescriptionInterface* sdesc) {
250*d9f75844SAndroid Build Coastguard Worker     auto* desc = sdesc->description();
251*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(desc->contents().size() > 0);
252*d9f75844SAndroid Build Coastguard Worker     auto* transport_info =
253*d9f75844SAndroid Build Coastguard Worker         desc->GetTransportInfoByName(desc->contents()[0].name);
254*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(transport_info);
255*d9f75844SAndroid Build Coastguard Worker     return &transport_info->description;
256*d9f75844SAndroid Build Coastguard Worker   }
257*d9f75844SAndroid Build Coastguard Worker 
258*d9f75844SAndroid Build Coastguard Worker   // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
259*d9f75844SAndroid Build Coastguard Worker   // after it is implemented.
GetIceRole(const WrapperPtr & pc_wrapper_ptr)260*d9f75844SAndroid Build Coastguard Worker   cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
261*d9f75844SAndroid Build Coastguard Worker     auto* pc_proxy =
262*d9f75844SAndroid Build Coastguard Worker         static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
263*d9f75844SAndroid Build Coastguard Worker             pc_wrapper_ptr->pc());
264*d9f75844SAndroid Build Coastguard Worker     PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
265*d9f75844SAndroid Build Coastguard Worker     for (const auto& transceiver : pc->GetTransceiversInternal()) {
266*d9f75844SAndroid Build Coastguard Worker       if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
267*d9f75844SAndroid Build Coastguard Worker         auto dtls_transport = pc->LookupDtlsTransportByMidInternal(
268*d9f75844SAndroid Build Coastguard Worker             transceiver->internal()->channel()->mid());
269*d9f75844SAndroid Build Coastguard Worker         return dtls_transport->ice_transport()->internal()->GetIceRole();
270*d9f75844SAndroid Build Coastguard Worker       }
271*d9f75844SAndroid Build Coastguard Worker     }
272*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED();
273*d9f75844SAndroid Build Coastguard Worker     return cricket::ICEROLE_UNKNOWN;
274*d9f75844SAndroid Build Coastguard Worker   }
275*d9f75844SAndroid Build Coastguard Worker 
276*d9f75844SAndroid Build Coastguard Worker   // Returns a list of (ufrag, pwd) pairs in the order that they appear in
277*d9f75844SAndroid Build Coastguard Worker   // `description`, or the empty list if `description` is null.
GetIceCredentials(const SessionDescriptionInterface * description)278*d9f75844SAndroid Build Coastguard Worker   std::vector<std::pair<std::string, std::string>> GetIceCredentials(
279*d9f75844SAndroid Build Coastguard Worker       const SessionDescriptionInterface* description) {
280*d9f75844SAndroid Build Coastguard Worker     std::vector<std::pair<std::string, std::string>> ice_credentials;
281*d9f75844SAndroid Build Coastguard Worker     if (!description)
282*d9f75844SAndroid Build Coastguard Worker       return ice_credentials;
283*d9f75844SAndroid Build Coastguard Worker     const auto* desc = description->description();
284*d9f75844SAndroid Build Coastguard Worker     for (const auto& content_info : desc->contents()) {
285*d9f75844SAndroid Build Coastguard Worker       const auto* transport_info =
286*d9f75844SAndroid Build Coastguard Worker           desc->GetTransportInfoByName(content_info.name);
287*d9f75844SAndroid Build Coastguard Worker       if (transport_info) {
288*d9f75844SAndroid Build Coastguard Worker         ice_credentials.push_back(
289*d9f75844SAndroid Build Coastguard Worker             std::make_pair(transport_info->description.ice_ufrag,
290*d9f75844SAndroid Build Coastguard Worker                            transport_info->description.ice_pwd));
291*d9f75844SAndroid Build Coastguard Worker       }
292*d9f75844SAndroid Build Coastguard Worker     }
293*d9f75844SAndroid Build Coastguard Worker     return ice_credentials;
294*d9f75844SAndroid Build Coastguard Worker   }
295*d9f75844SAndroid Build Coastguard Worker 
AddCandidateToFirstTransport(cricket::Candidate * candidate,SessionDescriptionInterface * sdesc)296*d9f75844SAndroid Build Coastguard Worker   bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
297*d9f75844SAndroid Build Coastguard Worker                                     SessionDescriptionInterface* sdesc) {
298*d9f75844SAndroid Build Coastguard Worker     auto* desc = sdesc->description();
299*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(desc->contents().size() > 0);
300*d9f75844SAndroid Build Coastguard Worker     const auto& first_content = desc->contents()[0];
301*d9f75844SAndroid Build Coastguard Worker     candidate->set_transport_name(first_content.name);
302*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<IceCandidateInterface> jsep_candidate =
303*d9f75844SAndroid Build Coastguard Worker         CreateIceCandidate(first_content.name, 0, *candidate);
304*d9f75844SAndroid Build Coastguard Worker     return sdesc->AddCandidate(jsep_candidate.get());
305*d9f75844SAndroid Build Coastguard Worker   }
306*d9f75844SAndroid Build Coastguard Worker 
NewFakeNetwork()307*d9f75844SAndroid Build Coastguard Worker   rtc::FakeNetworkManager* NewFakeNetwork() {
308*d9f75844SAndroid Build Coastguard Worker     // The PeerConnection's port allocator is tied to the PeerConnection's
309*d9f75844SAndroid Build Coastguard Worker     // lifetime and expects the underlying NetworkManager to outlive it. That
310*d9f75844SAndroid Build Coastguard Worker     // prevents us from having the PeerConnectionWrapper own the fake network.
311*d9f75844SAndroid Build Coastguard Worker     // Therefore, the test fixture will own all the fake networks even though
312*d9f75844SAndroid Build Coastguard Worker     // tests should access the fake network through the PeerConnectionWrapper.
313*d9f75844SAndroid Build Coastguard Worker     auto* fake_network = new rtc::FakeNetworkManager();
314*d9f75844SAndroid Build Coastguard Worker     fake_networks_.emplace_back(fake_network);
315*d9f75844SAndroid Build Coastguard Worker     return fake_network;
316*d9f75844SAndroid Build Coastguard Worker   }
317*d9f75844SAndroid Build Coastguard Worker 
318*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::VirtualSocketServer> vss_;
319*d9f75844SAndroid Build Coastguard Worker   rtc::AutoSocketServerThread main_;
320*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
321*d9f75844SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
322*d9f75844SAndroid Build Coastguard Worker   const SdpSemantics sdp_semantics_;
323*d9f75844SAndroid Build Coastguard Worker };
324*d9f75844SAndroid Build Coastguard Worker 
325*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceTest
326*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionIceBaseTest,
327*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<SdpSemantics> {
328*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionIceTest()329*d9f75844SAndroid Build Coastguard Worker   PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
330*d9f75844SAndroid Build Coastguard Worker     webrtc::metrics::Reset();
331*d9f75844SAndroid Build Coastguard Worker   }
332*d9f75844SAndroid Build Coastguard Worker };
333*d9f75844SAndroid Build Coastguard Worker 
AssertCandidatesEqual(const char * a_expr,const char * b_expr,const cricket::Candidate & a,const cricket::Candidate & b)334*d9f75844SAndroid Build Coastguard Worker ::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
335*d9f75844SAndroid Build Coastguard Worker                                                  const char* b_expr,
336*d9f75844SAndroid Build Coastguard Worker                                                  const cricket::Candidate& a,
337*d9f75844SAndroid Build Coastguard Worker                                                  const cricket::Candidate& b) {
338*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder failure_info;
339*d9f75844SAndroid Build Coastguard Worker   if (a.component() != b.component()) {
340*d9f75844SAndroid Build Coastguard Worker     failure_info << "\ncomponent: " << a.component() << " != " << b.component();
341*d9f75844SAndroid Build Coastguard Worker   }
342*d9f75844SAndroid Build Coastguard Worker   if (a.protocol() != b.protocol()) {
343*d9f75844SAndroid Build Coastguard Worker     failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
344*d9f75844SAndroid Build Coastguard Worker   }
345*d9f75844SAndroid Build Coastguard Worker   if (a.address() != b.address()) {
346*d9f75844SAndroid Build Coastguard Worker     failure_info << "\naddress: " << a.address().ToString()
347*d9f75844SAndroid Build Coastguard Worker                  << " != " << b.address().ToString();
348*d9f75844SAndroid Build Coastguard Worker   }
349*d9f75844SAndroid Build Coastguard Worker   if (a.type() != b.type()) {
350*d9f75844SAndroid Build Coastguard Worker     failure_info << "\ntype: " << a.type() << " != " << b.type();
351*d9f75844SAndroid Build Coastguard Worker   }
352*d9f75844SAndroid Build Coastguard Worker   std::string failure_info_str = failure_info.str();
353*d9f75844SAndroid Build Coastguard Worker   if (failure_info_str.empty()) {
354*d9f75844SAndroid Build Coastguard Worker     return ::testing::AssertionSuccess();
355*d9f75844SAndroid Build Coastguard Worker   } else {
356*d9f75844SAndroid Build Coastguard Worker     return ::testing::AssertionFailure()
357*d9f75844SAndroid Build Coastguard Worker            << a_expr << " and " << b_expr << " are not equal"
358*d9f75844SAndroid Build Coastguard Worker            << failure_info_str;
359*d9f75844SAndroid Build Coastguard Worker   }
360*d9f75844SAndroid Build Coastguard Worker }
361*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,OfferContainsGatheredCandidates)362*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
363*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress("1.1.1.1", 0);
364*d9f75844SAndroid Build Coastguard Worker 
365*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
366*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress);
367*d9f75844SAndroid Build Coastguard Worker 
368*d9f75844SAndroid Build Coastguard Worker   // Start ICE candidate gathering by setting the local offer.
369*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
370*d9f75844SAndroid Build Coastguard Worker 
371*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
372*d9f75844SAndroid Build Coastguard Worker 
373*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
374*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
375*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
376*d9f75844SAndroid Build Coastguard Worker             offer->candidates(0)->count());
377*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
378*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
379*d9f75844SAndroid Build Coastguard Worker             offer->candidates(1)->count());
380*d9f75844SAndroid Build Coastguard Worker }
381*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AnswerContainsGatheredCandidates)382*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
383*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress("1.1.1.1", 0);
384*d9f75844SAndroid Build Coastguard Worker 
385*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
386*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
387*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kCallerAddress);
388*d9f75844SAndroid Build Coastguard Worker 
389*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
390*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
391*d9f75844SAndroid Build Coastguard Worker 
392*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
393*d9f75844SAndroid Build Coastguard Worker 
394*d9f75844SAndroid Build Coastguard Worker   auto* answer = callee->pc()->local_description();
395*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
396*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
397*d9f75844SAndroid Build Coastguard Worker             answer->candidates(0)->count());
398*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
399*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
400*d9f75844SAndroid Build Coastguard Worker             answer->candidates(1)->count());
401*d9f75844SAndroid Build Coastguard Worker }
402*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,CanSetRemoteSessionDescriptionWithRemoteCandidates)403*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
404*d9f75844SAndroid Build Coastguard Worker        CanSetRemoteSessionDescriptionWithRemoteCandidates) {
405*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress("1.1.1.1", 1111);
406*d9f75844SAndroid Build Coastguard Worker 
407*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
408*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
409*d9f75844SAndroid Build Coastguard Worker 
410*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
411*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
412*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&candidate, offer.get());
413*d9f75844SAndroid Build Coastguard Worker 
414*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
415*d9f75844SAndroid Build Coastguard Worker   auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
416*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, remote_candidates.size());
417*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
418*d9f75844SAndroid Build Coastguard Worker                       remote_candidates[0]->candidate());
419*d9f75844SAndroid Build Coastguard Worker }
420*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,SetLocalDescriptionFailsIfNoIceCredentials)421*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
422*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
423*d9f75844SAndroid Build Coastguard Worker 
424*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
425*d9f75844SAndroid Build Coastguard Worker   RemoveIceUfragPwd(offer.get());
426*d9f75844SAndroid Build Coastguard Worker 
427*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
428*d9f75844SAndroid Build Coastguard Worker }
429*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,SetRemoteDescriptionFailsIfNoIceCredentials)430*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
431*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
432*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
433*d9f75844SAndroid Build Coastguard Worker 
434*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
435*d9f75844SAndroid Build Coastguard Worker   RemoveIceUfragPwd(offer.get());
436*d9f75844SAndroid Build Coastguard Worker 
437*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
438*d9f75844SAndroid Build Coastguard Worker }
439*d9f75844SAndroid Build Coastguard Worker 
440*d9f75844SAndroid Build Coastguard Worker // Test that doing an offer/answer exchange with no transport (i.e., no data
441*d9f75844SAndroid Build Coastguard Worker // channel or media) results in the ICE connection state staying at New.
TEST_P(PeerConnectionIceTest,OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState)442*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
443*d9f75844SAndroid Build Coastguard Worker        OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
444*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnection();
445*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnection();
446*d9f75844SAndroid Build Coastguard Worker 
447*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
448*d9f75844SAndroid Build Coastguard Worker 
449*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
450*d9f75844SAndroid Build Coastguard Worker             caller->pc()->ice_connection_state());
451*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
452*d9f75844SAndroid Build Coastguard Worker             callee->pc()->ice_connection_state());
453*d9f75844SAndroid Build Coastguard Worker }
454*d9f75844SAndroid Build Coastguard Worker 
455*d9f75844SAndroid Build Coastguard Worker // The following group tests that ICE candidates are not generated before
456*d9f75844SAndroid Build Coastguard Worker // SetLocalDescription is called on a PeerConnection.
457*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,NoIceCandidatesBeforeSetLocalDescription)458*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
459*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress("1.1.1.1", 0);
460*d9f75844SAndroid Build Coastguard Worker 
461*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
462*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress);
463*d9f75844SAndroid Build Coastguard Worker 
464*d9f75844SAndroid Build Coastguard Worker   // Pump for 1 second and verify that no candidates are generated.
465*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::Current()->ProcessMessages(1000);
466*d9f75844SAndroid Build Coastguard Worker 
467*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, caller->observer()->candidates_.size());
468*d9f75844SAndroid Build Coastguard Worker }
TEST_P(PeerConnectionIceTest,NoIceCandidatesBeforeAnswerSetAsLocalDescription)469*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
470*d9f75844SAndroid Build Coastguard Worker        NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
471*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress("1.1.1.1", 1111);
472*d9f75844SAndroid Build Coastguard Worker 
473*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
474*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
475*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kCallerAddress);
476*d9f75844SAndroid Build Coastguard Worker 
477*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
478*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
479*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&candidate, offer.get());
480*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
481*d9f75844SAndroid Build Coastguard Worker 
482*d9f75844SAndroid Build Coastguard Worker   // Pump for 1 second and verify that no candidates are generated.
483*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::Current()->ProcessMessages(1000);
484*d9f75844SAndroid Build Coastguard Worker 
485*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee->observer()->candidates_.size());
486*d9f75844SAndroid Build Coastguard Worker }
487*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,CannotAddCandidateWhenRemoteDescriptionNotSet)488*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
489*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
490*d9f75844SAndroid Build Coastguard Worker 
491*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
492*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
493*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jsep_candidate =
494*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
495*d9f75844SAndroid Build Coastguard Worker 
496*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
497*d9f75844SAndroid Build Coastguard Worker 
498*d9f75844SAndroid Build Coastguard Worker   caller->CreateOfferAndSetAsLocal();
499*d9f75844SAndroid Build Coastguard Worker 
500*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
501*d9f75844SAndroid Build Coastguard Worker   EXPECT_METRIC_THAT(
502*d9f75844SAndroid Build Coastguard Worker       webrtc::metrics::Samples("WebRTC.PeerConnection.AddIceCandidate"),
503*d9f75844SAndroid Build Coastguard Worker       ElementsAre(Pair(kAddIceCandidateFailNoRemoteDescription, 2)));
504*d9f75844SAndroid Build Coastguard Worker }
505*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,CannotAddCandidateWhenPeerConnectionClosed)506*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
507*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
508*d9f75844SAndroid Build Coastguard Worker 
509*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
510*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
511*d9f75844SAndroid Build Coastguard Worker 
512*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
513*d9f75844SAndroid Build Coastguard Worker 
514*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
515*d9f75844SAndroid Build Coastguard Worker   auto* audio_content = cricket::GetFirstAudioContent(
516*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->description());
517*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jsep_candidate =
518*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(audio_content->name, 0, candidate);
519*d9f75844SAndroid Build Coastguard Worker 
520*d9f75844SAndroid Build Coastguard Worker   caller->pc()->Close();
521*d9f75844SAndroid Build Coastguard Worker 
522*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
523*d9f75844SAndroid Build Coastguard Worker }
524*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,DuplicateIceCandidateIgnoredWhenAdded)525*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
526*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
527*d9f75844SAndroid Build Coastguard Worker 
528*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
529*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
530*d9f75844SAndroid Build Coastguard Worker 
531*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
532*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
533*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
534*d9f75844SAndroid Build Coastguard Worker 
535*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
536*d9f75844SAndroid Build Coastguard Worker   caller->AddIceCandidate(&candidate);
537*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->AddIceCandidate(&candidate));
538*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
539*d9f75844SAndroid Build Coastguard Worker }
540*d9f75844SAndroid Build Coastguard Worker 
541*d9f75844SAndroid Build Coastguard Worker // TODO(tommi): Re-enable after updating RTCPeerConnection-blockedPorts.html in
542*d9f75844SAndroid Build Coastguard Worker // Chromium (the test needs setRemoteDescription to succeed for an invalid
543*d9f75844SAndroid Build Coastguard Worker // candidate).
TEST_P(PeerConnectionIceTest,DISABLED_ErrorOnInvalidRemoteIceCandidateAdded)544*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, DISABLED_ErrorOnInvalidRemoteIceCandidateAdded) {
545*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
546*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
547*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
548*d9f75844SAndroid Build Coastguard Worker   // Add a candidate to the remote description with a candidate that has an
549*d9f75844SAndroid Build Coastguard Worker   // invalid address (port number == 2).
550*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswerAndSetAsLocal();
551*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate bad_candidate =
552*d9f75844SAndroid Build Coastguard Worker       CreateLocalUdpCandidate(SocketAddress("2.2.2.2", 2));
553*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Bad candidate: " << bad_candidate.ToString();
554*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&bad_candidate, answer.get());
555*d9f75844SAndroid Build Coastguard Worker   // Now the call to SetRemoteDescription should fail.
556*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->SetRemoteDescription(std::move(answer)));
557*d9f75844SAndroid Build Coastguard Worker }
558*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,CannotRemoveIceCandidatesWhenPeerConnectionClosed)559*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
560*d9f75844SAndroid Build Coastguard Worker        CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
561*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
562*d9f75844SAndroid Build Coastguard Worker 
563*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
564*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
565*d9f75844SAndroid Build Coastguard Worker 
566*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
567*d9f75844SAndroid Build Coastguard Worker 
568*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
569*d9f75844SAndroid Build Coastguard Worker   auto* audio_content = cricket::GetFirstAudioContent(
570*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->description());
571*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> ice_candidate =
572*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(audio_content->name, 0, candidate);
573*d9f75844SAndroid Build Coastguard Worker 
574*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
575*d9f75844SAndroid Build Coastguard Worker 
576*d9f75844SAndroid Build Coastguard Worker   caller->pc()->Close();
577*d9f75844SAndroid Build Coastguard Worker 
578*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
579*d9f75844SAndroid Build Coastguard Worker }
580*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AddRemoveCandidateWithEmptyTransportDoesNotCrash)581*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
582*d9f75844SAndroid Build Coastguard Worker        AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
583*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
584*d9f75844SAndroid Build Coastguard Worker 
585*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
586*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
587*d9f75844SAndroid Build Coastguard Worker 
588*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
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   // `candidate.transport_name()` is empty.
593*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
594*d9f75844SAndroid Build Coastguard Worker   auto* audio_content = cricket::GetFirstAudioContent(
595*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->description());
596*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> ice_candidate =
597*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(audio_content->name, 0, candidate);
598*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
599*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
600*d9f75844SAndroid Build Coastguard Worker }
601*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RemoveCandidateRemovesFromRemoteDescription)602*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
603*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
604*d9f75844SAndroid Build Coastguard Worker 
605*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
606*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
607*d9f75844SAndroid Build Coastguard Worker 
608*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
609*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
610*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
611*d9f75844SAndroid Build Coastguard Worker 
612*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
613*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->AddIceCandidate(&candidate));
614*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
615*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
616*d9f75844SAndroid Build Coastguard Worker }
617*d9f75844SAndroid Build Coastguard Worker 
618*d9f75844SAndroid Build Coastguard Worker // Test that if a candidate is added via AddIceCandidate and via an updated
619*d9f75844SAndroid Build Coastguard Worker // remote description, then both candidates appear in the stored remote
620*d9f75844SAndroid Build Coastguard Worker // description.
TEST_P(PeerConnectionIceTest,CandidateInSubsequentOfferIsAddedToRemoteDescription)621*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
622*d9f75844SAndroid Build Coastguard Worker        CandidateInSubsequentOfferIsAddedToRemoteDescription) {
623*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress1("1.1.1.1", 1111);
624*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress2("2.2.2.2", 2222);
625*d9f75844SAndroid Build Coastguard Worker 
626*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
627*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
628*d9f75844SAndroid Build Coastguard Worker 
629*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
630*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
631*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
632*d9f75844SAndroid Build Coastguard Worker 
633*d9f75844SAndroid Build Coastguard Worker   // Add one candidate via `AddIceCandidate`.
634*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
635*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
636*d9f75844SAndroid Build Coastguard Worker 
637*d9f75844SAndroid Build Coastguard Worker   // Add the second candidate via a reoffer.
638*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
639*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
640*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&candidate2, offer.get());
641*d9f75844SAndroid Build Coastguard Worker 
642*d9f75844SAndroid Build Coastguard Worker   // Expect both candidates to appear in the callee's remote description.
643*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
644*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
645*d9f75844SAndroid Build Coastguard Worker }
646*d9f75844SAndroid Build Coastguard Worker 
647*d9f75844SAndroid Build Coastguard Worker // The follow test verifies that SetLocal/RemoteDescription fails when an offer
648*d9f75844SAndroid Build Coastguard Worker // has either ICE ufrag/pwd too short or too long and succeeds otherwise.
649*d9f75844SAndroid Build Coastguard Worker // The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
650*d9f75844SAndroid Build Coastguard Worker // pwd must be 22-256 characters and ufrag must be 4-256 characters.
TEST_P(PeerConnectionIceTest,VerifyUfragPwdLength)651*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
652*d9f75844SAndroid Build Coastguard Worker   auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
653*d9f75844SAndroid Build Coastguard Worker                                                             int pwd_len) {
654*d9f75844SAndroid Build Coastguard Worker     auto pc = CreatePeerConnectionWithAudioVideo();
655*d9f75844SAndroid Build Coastguard Worker     auto offer = pc->CreateOffer();
656*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
657*d9f75844SAndroid Build Coastguard Worker                    std::string(pwd_len, 'x'));
658*d9f75844SAndroid Build Coastguard Worker     return pc->SetLocalDescription(std::move(offer));
659*d9f75844SAndroid Build Coastguard Worker   };
660*d9f75844SAndroid Build Coastguard Worker 
661*d9f75844SAndroid Build Coastguard Worker   auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
662*d9f75844SAndroid Build Coastguard Worker                                                              int pwd_len) {
663*d9f75844SAndroid Build Coastguard Worker     auto pc = CreatePeerConnectionWithAudioVideo();
664*d9f75844SAndroid Build Coastguard Worker     auto offer = pc->CreateOffer();
665*d9f75844SAndroid Build Coastguard Worker     SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
666*d9f75844SAndroid Build Coastguard Worker                    std::string(pwd_len, 'x'));
667*d9f75844SAndroid Build Coastguard Worker     return pc->SetRemoteDescription(std::move(offer));
668*d9f75844SAndroid Build Coastguard Worker   };
669*d9f75844SAndroid Build Coastguard Worker 
670*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
671*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
672*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
673*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
674*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
675*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
676*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
677*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
678*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
679*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
680*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
681*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
682*d9f75844SAndroid Build Coastguard Worker }
683*d9f75844SAndroid Build Coastguard Worker 
AssertIpInCandidates(const char * address_expr,const char * candidates_expr,const SocketAddress & address,const std::vector<IceCandidateInterface * > candidates)684*d9f75844SAndroid Build Coastguard Worker ::testing::AssertionResult AssertIpInCandidates(
685*d9f75844SAndroid Build Coastguard Worker     const char* address_expr,
686*d9f75844SAndroid Build Coastguard Worker     const char* candidates_expr,
687*d9f75844SAndroid Build Coastguard Worker     const SocketAddress& address,
688*d9f75844SAndroid Build Coastguard Worker     const std::vector<IceCandidateInterface*> candidates) {
689*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder candidate_hosts;
690*d9f75844SAndroid Build Coastguard Worker   for (const auto* candidate : candidates) {
691*d9f75844SAndroid Build Coastguard Worker     const auto& candidate_ip = candidate->candidate().address().ipaddr();
692*d9f75844SAndroid Build Coastguard Worker     if (candidate_ip == address.ipaddr()) {
693*d9f75844SAndroid Build Coastguard Worker       return ::testing::AssertionSuccess();
694*d9f75844SAndroid Build Coastguard Worker     }
695*d9f75844SAndroid Build Coastguard Worker     candidate_hosts << "\n" << candidate_ip.ToString();
696*d9f75844SAndroid Build Coastguard Worker   }
697*d9f75844SAndroid Build Coastguard Worker   return ::testing::AssertionFailure()
698*d9f75844SAndroid Build Coastguard Worker          << address_expr << " (host " << address.HostAsURIString()
699*d9f75844SAndroid Build Coastguard Worker          << ") not in " << candidates_expr
700*d9f75844SAndroid Build Coastguard Worker          << " which have the following address hosts:" << candidate_hosts.str();
701*d9f75844SAndroid Build Coastguard Worker }
702*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,CandidatesGeneratedForEachLocalInterface)703*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
704*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress1("1.1.1.1", 0);
705*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress2("2.2.2.2", 0);
706*d9f75844SAndroid Build Coastguard Worker 
707*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
708*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress1);
709*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress2);
710*d9f75844SAndroid Build Coastguard Worker 
711*d9f75844SAndroid Build Coastguard Worker   caller->CreateOfferAndSetAsLocal();
712*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
713*d9f75844SAndroid Build Coastguard Worker 
714*d9f75844SAndroid Build Coastguard Worker   auto candidates = caller->observer()->GetCandidatesByMline(0);
715*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
716*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
717*d9f75844SAndroid Build Coastguard Worker }
718*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,TrickledSingleCandidateAddedToRemoteDescription)719*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
720*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress("1.1.1.1", 1111);
721*d9f75844SAndroid Build Coastguard Worker 
722*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
723*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
724*d9f75844SAndroid Build Coastguard Worker 
725*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
726*d9f75844SAndroid Build Coastguard Worker 
727*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
728*d9f75844SAndroid Build Coastguard Worker   callee->AddIceCandidate(&candidate);
729*d9f75844SAndroid Build Coastguard Worker   auto candidates = callee->GetIceCandidatesFromRemoteDescription();
730*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, candidates.size());
731*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
732*d9f75844SAndroid Build Coastguard Worker                       candidates[0]->candidate());
733*d9f75844SAndroid Build Coastguard Worker }
734*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,TwoTrickledCandidatesAddedToRemoteDescription)735*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
736*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
737*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
738*d9f75844SAndroid Build Coastguard Worker 
739*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
740*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
741*d9f75844SAndroid Build Coastguard Worker 
742*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
743*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
744*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
745*d9f75844SAndroid Build Coastguard Worker 
746*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
747*d9f75844SAndroid Build Coastguard Worker   caller->AddIceCandidate(&candidate1);
748*d9f75844SAndroid Build Coastguard Worker 
749*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
750*d9f75844SAndroid Build Coastguard Worker   caller->AddIceCandidate(&candidate2);
751*d9f75844SAndroid Build Coastguard Worker 
752*d9f75844SAndroid Build Coastguard Worker   auto candidates = caller->GetIceCandidatesFromRemoteDescription();
753*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(2u, candidates.size());
754*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
755*d9f75844SAndroid Build Coastguard Worker                       candidates[0]->candidate());
756*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
757*d9f75844SAndroid Build Coastguard Worker                       candidates[1]->candidate());
758*d9f75844SAndroid Build Coastguard Worker }
759*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateIsAddedToRemoteDescription)760*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, AsyncAddIceCandidateIsAddedToRemoteDescription) {
761*d9f75844SAndroid Build Coastguard Worker   auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
762*d9f75844SAndroid Build Coastguard Worker 
763*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
764*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
765*d9f75844SAndroid Build Coastguard Worker 
766*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
767*d9f75844SAndroid Build Coastguard Worker 
768*d9f75844SAndroid Build Coastguard Worker   auto jsep_candidate =
769*d9f75844SAndroid Build Coastguard Worker       callee->CreateJsepCandidateForFirstTransport(&candidate);
770*d9f75844SAndroid Build Coastguard Worker   bool operation_completed = false;
771*d9f75844SAndroid Build Coastguard Worker   callee->pc()->AddIceCandidate(std::move(jsep_candidate),
772*d9f75844SAndroid Build Coastguard Worker                                 [&operation_completed](RTCError result) {
773*d9f75844SAndroid Build Coastguard Worker                                   EXPECT_TRUE(result.ok());
774*d9f75844SAndroid Build Coastguard Worker                                   operation_completed = true;
775*d9f75844SAndroid Build Coastguard Worker                                 });
776*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
777*d9f75844SAndroid Build Coastguard Worker 
778*d9f75844SAndroid Build Coastguard Worker   auto candidates = callee->GetIceCandidatesFromRemoteDescription();
779*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, candidates.size());
780*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
781*d9f75844SAndroid Build Coastguard Worker                       candidates[0]->candidate());
782*d9f75844SAndroid Build Coastguard Worker }
783*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateCompletesImmediatelyIfNoPendingOperation)784*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
785*d9f75844SAndroid Build Coastguard Worker        AsyncAddIceCandidateCompletesImmediatelyIfNoPendingOperation) {
786*d9f75844SAndroid Build Coastguard Worker   auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
787*d9f75844SAndroid Build Coastguard Worker 
788*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
789*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
790*d9f75844SAndroid Build Coastguard Worker 
791*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
792*d9f75844SAndroid Build Coastguard Worker 
793*d9f75844SAndroid Build Coastguard Worker   auto jsep_candidate =
794*d9f75844SAndroid Build Coastguard Worker       callee->CreateJsepCandidateForFirstTransport(&candidate);
795*d9f75844SAndroid Build Coastguard Worker   bool operation_completed = false;
796*d9f75844SAndroid Build Coastguard Worker   callee->pc()->AddIceCandidate(
797*d9f75844SAndroid Build Coastguard Worker       std::move(jsep_candidate),
798*d9f75844SAndroid Build Coastguard Worker       [&operation_completed](RTCError result) { operation_completed = true; });
799*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(operation_completed);
800*d9f75844SAndroid Build Coastguard Worker }
801*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateCompletesWhenPendingOperationCompletes)802*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
803*d9f75844SAndroid Build Coastguard Worker        AsyncAddIceCandidateCompletesWhenPendingOperationCompletes) {
804*d9f75844SAndroid Build Coastguard Worker   auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
805*d9f75844SAndroid Build Coastguard Worker 
806*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
807*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
808*d9f75844SAndroid Build Coastguard Worker 
809*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
810*d9f75844SAndroid Build Coastguard Worker 
811*d9f75844SAndroid Build Coastguard Worker   // Chain an operation that will block AddIceCandidate() from executing.
812*d9f75844SAndroid Build Coastguard Worker   auto answer_observer =
813*d9f75844SAndroid Build Coastguard Worker       rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
814*d9f75844SAndroid Build Coastguard Worker   callee->pc()->CreateAnswer(answer_observer.get(), RTCOfferAnswerOptions());
815*d9f75844SAndroid Build Coastguard Worker 
816*d9f75844SAndroid Build Coastguard Worker   auto jsep_candidate =
817*d9f75844SAndroid Build Coastguard Worker       callee->CreateJsepCandidateForFirstTransport(&candidate);
818*d9f75844SAndroid Build Coastguard Worker   bool operation_completed = false;
819*d9f75844SAndroid Build Coastguard Worker   callee->pc()->AddIceCandidate(
820*d9f75844SAndroid Build Coastguard Worker       std::move(jsep_candidate),
821*d9f75844SAndroid Build Coastguard Worker       [&operation_completed](RTCError result) { operation_completed = true; });
822*d9f75844SAndroid Build Coastguard Worker   // The operation will not be able to complete until we EXPECT_TRUE_WAIT()
823*d9f75844SAndroid Build Coastguard Worker   // allowing CreateAnswer() to complete.
824*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(operation_completed);
825*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(answer_observer->called(), kWaitTimeout);
826*d9f75844SAndroid Build Coastguard Worker   // As soon as it does, AddIceCandidate() will execute without delay, so it
827*d9f75844SAndroid Build Coastguard Worker   // must also have completed.
828*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(operation_completed);
829*d9f75844SAndroid Build Coastguard Worker }
830*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateFailsBeforeSetRemoteDescription)831*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
832*d9f75844SAndroid Build Coastguard Worker        AsyncAddIceCandidateFailsBeforeSetRemoteDescription) {
833*d9f75844SAndroid Build Coastguard Worker   auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
834*d9f75844SAndroid Build Coastguard Worker 
835*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
836*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> jsep_candidate =
837*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
838*d9f75844SAndroid Build Coastguard Worker 
839*d9f75844SAndroid Build Coastguard Worker   bool operation_completed = false;
840*d9f75844SAndroid Build Coastguard Worker   caller->pc()->AddIceCandidate(
841*d9f75844SAndroid Build Coastguard Worker       std::move(jsep_candidate), [&operation_completed](RTCError result) {
842*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(result.ok());
843*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(result.message(),
844*d9f75844SAndroid Build Coastguard Worker                   std::string("The remote description was null"));
845*d9f75844SAndroid Build Coastguard Worker         operation_completed = true;
846*d9f75844SAndroid Build Coastguard Worker       });
847*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
848*d9f75844SAndroid Build Coastguard Worker }
849*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,AsyncAddIceCandidateFailsIfPeerConnectionDestroyed)850*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
851*d9f75844SAndroid Build Coastguard Worker        AsyncAddIceCandidateFailsIfPeerConnectionDestroyed) {
852*d9f75844SAndroid Build Coastguard Worker   auto candidate = CreateLocalUdpCandidate(SocketAddress("1.1.1.1", 1111));
853*d9f75844SAndroid Build Coastguard Worker 
854*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
855*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
856*d9f75844SAndroid Build Coastguard Worker 
857*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
858*d9f75844SAndroid Build Coastguard Worker 
859*d9f75844SAndroid Build Coastguard Worker   // Chain an operation that will block AddIceCandidate() from executing.
860*d9f75844SAndroid Build Coastguard Worker   auto answer_observer =
861*d9f75844SAndroid Build Coastguard Worker       rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
862*d9f75844SAndroid Build Coastguard Worker   callee->pc()->CreateAnswer(answer_observer.get(), RTCOfferAnswerOptions());
863*d9f75844SAndroid Build Coastguard Worker 
864*d9f75844SAndroid Build Coastguard Worker   auto jsep_candidate =
865*d9f75844SAndroid Build Coastguard Worker       callee->CreateJsepCandidateForFirstTransport(&candidate);
866*d9f75844SAndroid Build Coastguard Worker   bool operation_completed = false;
867*d9f75844SAndroid Build Coastguard Worker   callee->pc()->AddIceCandidate(
868*d9f75844SAndroid Build Coastguard Worker       std::move(jsep_candidate), [&operation_completed](RTCError result) {
869*d9f75844SAndroid Build Coastguard Worker         EXPECT_FALSE(result.ok());
870*d9f75844SAndroid Build Coastguard Worker         EXPECT_EQ(
871*d9f75844SAndroid Build Coastguard Worker             result.message(),
872*d9f75844SAndroid Build Coastguard Worker             std::string(
873*d9f75844SAndroid Build Coastguard Worker                 "AddIceCandidate failed because the session was shut down"));
874*d9f75844SAndroid Build Coastguard Worker         operation_completed = true;
875*d9f75844SAndroid Build Coastguard Worker       });
876*d9f75844SAndroid Build Coastguard Worker   // The operation will not be able to run until EXPECT_TRUE_WAIT(), giving us
877*d9f75844SAndroid Build Coastguard Worker   // time to remove all references to the PeerConnection.
878*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(operation_completed);
879*d9f75844SAndroid Build Coastguard Worker   // This should delete the callee PC.
880*d9f75844SAndroid Build Coastguard Worker   callee = nullptr;
881*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(operation_completed, kWaitTimeout);
882*d9f75844SAndroid Build Coastguard Worker }
883*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,LocalDescriptionUpdatedWhenContinualGathering)884*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
885*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress("1.1.1.1", 0);
886*d9f75844SAndroid Build Coastguard Worker 
887*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
888*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
889*d9f75844SAndroid Build Coastguard Worker   config.continual_gathering_policy =
890*d9f75844SAndroid Build Coastguard Worker       PeerConnectionInterface::GATHER_CONTINUALLY;
891*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(config);
892*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress);
893*d9f75844SAndroid Build Coastguard Worker 
894*d9f75844SAndroid Build Coastguard Worker   // Start ICE candidate gathering by setting the local offer.
895*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
896*d9f75844SAndroid Build Coastguard Worker 
897*d9f75844SAndroid Build Coastguard Worker   // Since we're using continual gathering, we won't get "gathering done".
898*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(
899*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->candidates(0)->count() > 0,
900*d9f75844SAndroid Build Coastguard Worker       kIceCandidatesTimeout);
901*d9f75844SAndroid Build Coastguard Worker }
902*d9f75844SAndroid Build Coastguard Worker 
903*d9f75844SAndroid Build Coastguard Worker // Test that when continual gathering is enabled, and a network interface goes
904*d9f75844SAndroid Build Coastguard Worker // down, the candidate is signaled as removed and removed from the local
905*d9f75844SAndroid Build Coastguard Worker // description.
TEST_P(PeerConnectionIceTest,LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually)906*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
907*d9f75844SAndroid Build Coastguard Worker        LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
908*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress("1.1.1.1", 0);
909*d9f75844SAndroid Build Coastguard Worker 
910*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
911*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
912*d9f75844SAndroid Build Coastguard Worker   config.continual_gathering_policy =
913*d9f75844SAndroid Build Coastguard Worker       PeerConnectionInterface::GATHER_CONTINUALLY;
914*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(config);
915*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress);
916*d9f75844SAndroid Build Coastguard Worker 
917*d9f75844SAndroid Build Coastguard Worker   // Start ICE candidate gathering by setting the local offer.
918*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
919*d9f75844SAndroid Build Coastguard Worker 
920*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(
921*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->candidates(0)->count() > 0,
922*d9f75844SAndroid Build Coastguard Worker       kIceCandidatesTimeout);
923*d9f75844SAndroid Build Coastguard Worker 
924*d9f75844SAndroid Build Coastguard Worker   // Remove the only network interface, causing the PeerConnection to signal
925*d9f75844SAndroid Build Coastguard Worker   // the removal of all candidates derived from this interface.
926*d9f75844SAndroid Build Coastguard Worker   caller->network()->RemoveInterface(kLocalAddress);
927*d9f75844SAndroid Build Coastguard Worker 
928*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
929*d9f75844SAndroid Build Coastguard Worker                  kIceCandidatesTimeout);
930*d9f75844SAndroid Build Coastguard Worker   EXPECT_LT(0, caller->observer()->num_candidates_removed_);
931*d9f75844SAndroid Build Coastguard Worker }
932*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce)933*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
934*d9f75844SAndroid Build Coastguard Worker        LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
935*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kLocalAddress("1.1.1.1", 0);
936*d9f75844SAndroid Build Coastguard Worker 
937*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
938*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
939*d9f75844SAndroid Build Coastguard Worker   config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
940*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo(config);
941*d9f75844SAndroid Build Coastguard Worker   caller->network()->AddInterface(kLocalAddress);
942*d9f75844SAndroid Build Coastguard Worker 
943*d9f75844SAndroid Build Coastguard Worker   // Start ICE candidate gathering by setting the local offer.
944*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
945*d9f75844SAndroid Build Coastguard Worker 
946*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
947*d9f75844SAndroid Build Coastguard Worker 
948*d9f75844SAndroid Build Coastguard Worker   caller->network()->RemoveInterface(kLocalAddress);
949*d9f75844SAndroid Build Coastguard Worker 
950*d9f75844SAndroid Build Coastguard Worker   // Verify that the local candidates are not removed;
951*d9f75844SAndroid Build Coastguard Worker   rtc::Thread::Current()->ProcessMessages(1000);
952*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
953*d9f75844SAndroid Build Coastguard Worker }
954*d9f75844SAndroid Build Coastguard Worker 
955*d9f75844SAndroid Build Coastguard Worker // The following group tests that when an offer includes a new ufrag or pwd
956*d9f75844SAndroid Build Coastguard Worker // (indicating an ICE restart) the old candidates are removed and new candidates
957*d9f75844SAndroid Build Coastguard Worker // added to the remote description.
958*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,IceRestartOfferClearsExistingCandidate)959*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
960*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCallerAddress("1.1.1.1", 1111);
961*d9f75844SAndroid Build Coastguard Worker 
962*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
963*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
964*d9f75844SAndroid Build Coastguard Worker 
965*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
966*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
967*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&candidate, offer.get());
968*d9f75844SAndroid Build Coastguard Worker 
969*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
970*d9f75844SAndroid Build Coastguard Worker 
971*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
972*d9f75844SAndroid Build Coastguard Worker   options.ice_restart = true;
973*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
974*d9f75844SAndroid Build Coastguard Worker       callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
975*d9f75844SAndroid Build Coastguard Worker 
976*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
977*d9f75844SAndroid Build Coastguard Worker }
TEST_P(PeerConnectionIceTest,IceRestartOfferCandidateReplacesExistingCandidate)978*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
979*d9f75844SAndroid Build Coastguard Worker        IceRestartOfferCandidateReplacesExistingCandidate) {
980*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
981*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
982*d9f75844SAndroid Build Coastguard Worker 
983*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
984*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
985*d9f75844SAndroid Build Coastguard Worker 
986*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOfferAndSetAsLocal();
987*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate old_candidate =
988*d9f75844SAndroid Build Coastguard Worker       CreateLocalUdpCandidate(kFirstCallerAddress);
989*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&old_candidate, offer.get());
990*d9f75844SAndroid Build Coastguard Worker 
991*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
992*d9f75844SAndroid Build Coastguard Worker 
993*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions options;
994*d9f75844SAndroid Build Coastguard Worker   options.ice_restart = true;
995*d9f75844SAndroid Build Coastguard Worker   auto restart_offer = caller->CreateOfferAndSetAsLocal(options);
996*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate new_candidate =
997*d9f75844SAndroid Build Coastguard Worker       CreateLocalUdpCandidate(kRestartedCallerAddress);
998*d9f75844SAndroid Build Coastguard Worker   AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
999*d9f75844SAndroid Build Coastguard Worker 
1000*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
1001*d9f75844SAndroid Build Coastguard Worker 
1002*d9f75844SAndroid Build Coastguard Worker   auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
1003*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, remote_candidates.size());
1004*d9f75844SAndroid Build Coastguard Worker   EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
1005*d9f75844SAndroid Build Coastguard Worker                       remote_candidates[0]->candidate());
1006*d9f75844SAndroid Build Coastguard Worker }
1007*d9f75844SAndroid Build Coastguard Worker 
1008*d9f75844SAndroid Build Coastguard Worker // Test that if there is not an ICE restart (i.e., nothing changes), then the
1009*d9f75844SAndroid Build Coastguard Worker // answer to a later offer should have the same ufrag/pwd as the first answer.
TEST_P(PeerConnectionIceTest,LaterAnswerHasSameIceCredentialsIfNoIceRestart)1010*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
1011*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1012*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1013*d9f75844SAndroid Build Coastguard Worker 
1014*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1015*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1016*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1017*d9f75844SAndroid Build Coastguard Worker 
1018*d9f75844SAndroid Build Coastguard Worker   // Re-offer.
1019*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1020*d9f75844SAndroid Build Coastguard Worker 
1021*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1022*d9f75844SAndroid Build Coastguard Worker   auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
1023*d9f75844SAndroid Build Coastguard Worker   auto* local_transport_desc =
1024*d9f75844SAndroid Build Coastguard Worker       GetFirstTransportDescription(callee->pc()->local_description());
1025*d9f75844SAndroid Build Coastguard Worker 
1026*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
1027*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
1028*d9f75844SAndroid Build Coastguard Worker }
1029*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RestartIceGeneratesNewCredentials)1030*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, RestartIceGeneratesNewCredentials) {
1031*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1032*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1033*d9f75844SAndroid Build Coastguard Worker 
1034*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1035*d9f75844SAndroid Build Coastguard Worker   auto initial_ice_credentials =
1036*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1037*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1038*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
1039*d9f75844SAndroid Build Coastguard Worker   auto restarted_ice_credentials =
1040*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1041*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1042*d9f75844SAndroid Build Coastguard Worker }
1043*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer)1044*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
1045*d9f75844SAndroid Build Coastguard Worker        RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer) {
1046*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1047*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1048*d9f75844SAndroid Build Coastguard Worker 
1049*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1050*d9f75844SAndroid Build Coastguard Worker   auto initial_ice_credentials =
1051*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1052*d9f75844SAndroid Build Coastguard Worker   // ICE restart becomes needed while an O/A is pending and `caller` is the
1053*d9f75844SAndroid Build Coastguard Worker   // offerer.
1054*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1055*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1056*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1057*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
1058*d9f75844SAndroid Build Coastguard Worker   auto restarted_ice_credentials =
1059*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1060*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1061*d9f75844SAndroid Build Coastguard Worker }
1062*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer)1063*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
1064*d9f75844SAndroid Build Coastguard Worker        RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer) {
1065*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1066*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1067*d9f75844SAndroid Build Coastguard Worker 
1068*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1069*d9f75844SAndroid Build Coastguard Worker   auto initial_ice_credentials =
1070*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1071*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
1072*d9f75844SAndroid Build Coastguard Worker   // ICE restart becomes needed while an O/A is pending and `caller` is the
1073*d9f75844SAndroid Build Coastguard Worker   // answerer.
1074*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1075*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1076*d9f75844SAndroid Build Coastguard Worker       callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
1077*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
1078*d9f75844SAndroid Build Coastguard Worker   auto restarted_ice_credentials =
1079*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1080*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1081*d9f75844SAndroid Build Coastguard Worker }
1082*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RestartIceTriggeredByRemoteSide)1083*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, RestartIceTriggeredByRemoteSide) {
1084*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1085*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1086*d9f75844SAndroid Build Coastguard Worker 
1087*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1088*d9f75844SAndroid Build Coastguard Worker   auto initial_ice_credentials =
1089*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1090*d9f75844SAndroid Build Coastguard Worker 
1091*d9f75844SAndroid Build Coastguard Worker   // Remote restart and O/A exchange with `caller` as the answerer should
1092*d9f75844SAndroid Build Coastguard Worker   // restart ICE locally as well.
1093*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RestartIce();
1094*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1095*d9f75844SAndroid Build Coastguard Worker 
1096*d9f75844SAndroid Build Coastguard Worker   auto restarted_ice_credentials =
1097*d9f75844SAndroid Build Coastguard Worker       GetIceCredentials(caller->pc()->local_description());
1098*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
1099*d9f75844SAndroid Build Coastguard Worker }
1100*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,RestartIceCausesNegotiationNeeded)1101*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, RestartIceCausesNegotiationNeeded) {
1102*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1103*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1104*d9f75844SAndroid Build Coastguard Worker 
1105*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1106*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1107*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1108*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1109*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1110*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1111*d9f75844SAndroid Build Coastguard Worker }
1112*d9f75844SAndroid Build Coastguard Worker 
1113*d9f75844SAndroid Build Coastguard Worker // In Unified Plan, "onnegotiationneeded" is spec-compliant, including not
1114*d9f75844SAndroid Build Coastguard Worker // firing multipe times in a row, or firing when returning to the stable
1115*d9f75844SAndroid Build Coastguard Worker // signaling state if negotiation is still needed. In Plan B it fires any time
1116*d9f75844SAndroid Build Coastguard Worker // something changes. As such, some tests are SdpSemantics-specific.
1117*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceTestUnifiedPlan : public PeerConnectionIceBaseTest {
1118*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionIceTestUnifiedPlan()1119*d9f75844SAndroid Build Coastguard Worker   PeerConnectionIceTestUnifiedPlan()
1120*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionIceBaseTest(SdpSemantics::kUnifiedPlan) {}
1121*d9f75844SAndroid Build Coastguard Worker };
1122*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable)1123*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestUnifiedPlan,
1124*d9f75844SAndroid Build Coastguard Worker        RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable) {
1125*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1126*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1127*d9f75844SAndroid Build Coastguard Worker 
1128*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1129*d9f75844SAndroid Build Coastguard Worker   // ICE restart becomes needed while an O/A is pending and `caller` is the
1130*d9f75844SAndroid Build Coastguard Worker   // offerer.
1131*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1132*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1133*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1134*d9f75844SAndroid Build Coastguard Worker   // In Unified Plan, the event should not fire until we are back in the stable
1135*d9f75844SAndroid Build Coastguard Worker   // signaling state.
1136*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1137*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1138*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1139*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1140*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1141*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1142*d9f75844SAndroid Build Coastguard Worker }
1143*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable)1144*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestUnifiedPlan,
1145*d9f75844SAndroid Build Coastguard Worker        RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable) {
1146*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1147*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1148*d9f75844SAndroid Build Coastguard Worker 
1149*d9f75844SAndroid Build Coastguard Worker   // Establish initial credentials as the caller.
1150*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1151*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
1152*d9f75844SAndroid Build Coastguard Worker   // ICE restart becomes needed while an O/A is pending and `caller` is the
1153*d9f75844SAndroid Build Coastguard Worker   // answerer.
1154*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1155*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1156*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1157*d9f75844SAndroid Build Coastguard Worker   // In Unified Plan, the event should not fire until we are back in the stable
1158*d9f75844SAndroid Build Coastguard Worker   // signaling state.
1159*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1160*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1161*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1162*d9f75844SAndroid Build Coastguard Worker       callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
1163*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1164*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1165*d9f75844SAndroid Build Coastguard Worker }
1166*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded)1167*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestUnifiedPlan,
1168*d9f75844SAndroid Build Coastguard Worker        RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded) {
1169*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1170*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1171*d9f75844SAndroid Build Coastguard Worker 
1172*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1173*d9f75844SAndroid Build Coastguard Worker   // Local restart.
1174*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1175*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1176*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1177*d9f75844SAndroid Build Coastguard Worker   // Remote restart and O/A exchange with `caller` as the answerer should
1178*d9f75844SAndroid Build Coastguard Worker   // restart ICE locally as well.
1179*d9f75844SAndroid Build Coastguard Worker   callee->pc()->RestartIce();
1180*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
1181*d9f75844SAndroid Build Coastguard Worker   // Having restarted ICE by the remote offer, we do not need to renegotiate ICE
1182*d9f75844SAndroid Build Coastguard Worker   // credentials when back in the stable signaling state.
1183*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1184*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1185*d9f75844SAndroid Build Coastguard Worker }
1186*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestUnifiedPlan,RestartIceTwiceDoesNotFireNegotiationNeededTwice)1187*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestUnifiedPlan,
1188*d9f75844SAndroid Build Coastguard Worker        RestartIceTwiceDoesNotFireNegotiationNeededTwice) {
1189*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1190*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1191*d9f75844SAndroid Build Coastguard Worker 
1192*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1193*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1194*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1195*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1196*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1197*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1198*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1199*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1200*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1201*d9f75844SAndroid Build Coastguard Worker }
1202*d9f75844SAndroid Build Coastguard Worker 
1203*d9f75844SAndroid Build Coastguard Worker // In Plan B, "onnegotiationneeded" is not spec-compliant, firing based on if
1204*d9f75844SAndroid Build Coastguard Worker // something changed rather than if negotiation is needed. In Unified Plan it
1205*d9f75844SAndroid Build Coastguard Worker // fires according to spec. As such, some tests are SdpSemantics-specific.
1206*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceTestPlanB : public PeerConnectionIceBaseTest {
1207*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionIceTestPlanB()1208*d9f75844SAndroid Build Coastguard Worker   PeerConnectionIceTestPlanB()
1209*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionIceBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
1210*d9f75844SAndroid Build Coastguard Worker };
1211*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestPlanB,RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately)1212*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestPlanB,
1213*d9f75844SAndroid Build Coastguard Worker        RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately) {
1214*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1215*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1216*d9f75844SAndroid Build Coastguard Worker 
1217*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1218*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1219*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1220*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1221*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1222*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1223*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1224*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1225*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1226*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1227*d9f75844SAndroid Build Coastguard Worker   // In Plan B, the event fired early so we don't expect it to fire now. This is
1228*d9f75844SAndroid Build Coastguard Worker   // not spec-compliant but follows the pattern of existing Plan B behavior.
1229*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->legacy_renegotiation_needed());
1230*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1231*d9f75844SAndroid Build Coastguard Worker }
1232*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceTestPlanB,RestartIceTwiceDoesFireNegotiationNeededTwice)1233*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceTestPlanB,
1234*d9f75844SAndroid Build Coastguard Worker        RestartIceTwiceDoesFireNegotiationNeededTwice) {
1235*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1236*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1237*d9f75844SAndroid Build Coastguard Worker 
1238*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1239*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1240*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1241*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1242*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1243*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1244*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_legacy_renegotiation_needed();
1245*d9f75844SAndroid Build Coastguard Worker   caller->observer()->clear_latest_negotiation_needed_event();
1246*d9f75844SAndroid Build Coastguard Worker   caller->pc()->RestartIce();
1247*d9f75844SAndroid Build Coastguard Worker   // In Plan B, the event fires every time something changed, even if we have
1248*d9f75844SAndroid Build Coastguard Worker   // already fired the event. This is not spec-compliant but follows the same
1249*d9f75844SAndroid Build Coastguard Worker   // pattern of existing Plan B behavior.
1250*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->legacy_renegotiation_needed());
1251*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1252*d9f75844SAndroid Build Coastguard Worker }
1253*d9f75844SAndroid Build Coastguard Worker 
1254*d9f75844SAndroid Build Coastguard Worker // The following parameterized test verifies that if an offer is sent with a
1255*d9f75844SAndroid Build Coastguard Worker // modified ICE ufrag and/or ICE pwd, then the answer should identify that the
1256*d9f75844SAndroid Build Coastguard Worker // other side has initiated an ICE restart and generate a new ufrag and pwd.
1257*d9f75844SAndroid Build Coastguard Worker // RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
1258*d9f75844SAndroid Build Coastguard Worker // a=ice-pwd attributes compared to the previous SDP from the peer, it
1259*d9f75844SAndroid Build Coastguard Worker // indicates that ICE is restarting for this media stream."
1260*d9f75844SAndroid Build Coastguard Worker 
1261*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceUfragPwdAnswerTest
1262*d9f75844SAndroid Build Coastguard Worker     : public PeerConnectionIceBaseTest,
1263*d9f75844SAndroid Build Coastguard Worker       public ::testing::WithParamInterface<
1264*d9f75844SAndroid Build Coastguard Worker           std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
1265*d9f75844SAndroid Build Coastguard Worker  protected:
PeerConnectionIceUfragPwdAnswerTest()1266*d9f75844SAndroid Build Coastguard Worker   PeerConnectionIceUfragPwdAnswerTest()
1267*d9f75844SAndroid Build Coastguard Worker       : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
1268*d9f75844SAndroid Build Coastguard Worker     auto param = std::get<1>(GetParam());
1269*d9f75844SAndroid Build Coastguard Worker     offer_new_ufrag_ = std::get<0>(param);
1270*d9f75844SAndroid Build Coastguard Worker     offer_new_pwd_ = std::get<1>(param);
1271*d9f75844SAndroid Build Coastguard Worker   }
1272*d9f75844SAndroid Build Coastguard Worker 
1273*d9f75844SAndroid Build Coastguard Worker   bool offer_new_ufrag_;
1274*d9f75844SAndroid Build Coastguard Worker   bool offer_new_pwd_;
1275*d9f75844SAndroid Build Coastguard Worker };
1276*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceUfragPwdAnswerTest,TestIncludedInAnswer)1277*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
1278*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1279*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1280*d9f75844SAndroid Build Coastguard Worker 
1281*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1282*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1283*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1284*d9f75844SAndroid Build Coastguard Worker 
1285*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1286*d9f75844SAndroid Build Coastguard Worker   auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1287*d9f75844SAndroid Build Coastguard Worker   if (offer_new_ufrag_) {
1288*d9f75844SAndroid Build Coastguard Worker     offer_transport_desc->ice_ufrag += "+new";
1289*d9f75844SAndroid Build Coastguard Worker   }
1290*d9f75844SAndroid Build Coastguard Worker   if (offer_new_pwd_) {
1291*d9f75844SAndroid Build Coastguard Worker     offer_transport_desc->ice_pwd += "+new";
1292*d9f75844SAndroid Build Coastguard Worker   }
1293*d9f75844SAndroid Build Coastguard Worker 
1294*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1295*d9f75844SAndroid Build Coastguard Worker 
1296*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1297*d9f75844SAndroid Build Coastguard Worker   auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
1298*d9f75844SAndroid Build Coastguard Worker   auto* local_transport_desc =
1299*d9f75844SAndroid Build Coastguard Worker       GetFirstTransportDescription(callee->pc()->local_description());
1300*d9f75844SAndroid Build Coastguard Worker 
1301*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
1302*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
1303*d9f75844SAndroid Build Coastguard Worker }
1304*d9f75844SAndroid Build Coastguard Worker 
1305*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
1306*d9f75844SAndroid Build Coastguard Worker     PeerConnectionIceTest,
1307*d9f75844SAndroid Build Coastguard Worker     PeerConnectionIceUfragPwdAnswerTest,
1308*d9f75844SAndroid Build Coastguard Worker     Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
1309*d9f75844SAndroid Build Coastguard Worker             Values(std::make_pair(true, true),      // Both changed.
1310*d9f75844SAndroid Build Coastguard Worker                    std::make_pair(true, false),     // Only ufrag changed.
1311*d9f75844SAndroid Build Coastguard Worker                    std::make_pair(false, true))));  // Only pwd changed.
1312*d9f75844SAndroid Build Coastguard Worker 
1313*d9f75844SAndroid Build Coastguard Worker // Test that if an ICE restart is offered on one media section, then the answer
1314*d9f75844SAndroid Build Coastguard Worker // will only change ICE ufrag/pwd for that section and keep the other sections
1315*d9f75844SAndroid Build Coastguard Worker // the same.
1316*d9f75844SAndroid Build Coastguard Worker // Note that this only works if we have disabled BUNDLE, otherwise all media
1317*d9f75844SAndroid Build Coastguard Worker // sections will share the same transport.
TEST_P(PeerConnectionIceTest,CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted)1318*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
1319*d9f75844SAndroid Build Coastguard Worker        CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
1320*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1321*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1322*d9f75844SAndroid Build Coastguard Worker 
1323*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1324*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1325*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1326*d9f75844SAndroid Build Coastguard Worker 
1327*d9f75844SAndroid Build Coastguard Worker   RTCOfferAnswerOptions disable_bundle_options;
1328*d9f75844SAndroid Build Coastguard Worker   disable_bundle_options.use_rtp_mux = false;
1329*d9f75844SAndroid Build Coastguard Worker 
1330*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer(disable_bundle_options);
1331*d9f75844SAndroid Build Coastguard Worker 
1332*d9f75844SAndroid Build Coastguard Worker   // Signal ICE restart on the first media section.
1333*d9f75844SAndroid Build Coastguard Worker   auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1334*d9f75844SAndroid Build Coastguard Worker   offer_transport_desc->ice_ufrag += "+new";
1335*d9f75844SAndroid Build Coastguard Worker   offer_transport_desc->ice_pwd += "+new";
1336*d9f75844SAndroid Build Coastguard Worker 
1337*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1338*d9f75844SAndroid Build Coastguard Worker 
1339*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer(disable_bundle_options);
1340*d9f75844SAndroid Build Coastguard Worker   const auto& answer_transports = answer->description()->transport_infos();
1341*d9f75844SAndroid Build Coastguard Worker   const auto& local_transports =
1342*d9f75844SAndroid Build Coastguard Worker       callee->pc()->local_description()->description()->transport_infos();
1343*d9f75844SAndroid Build Coastguard Worker 
1344*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(answer_transports[0].description.ice_ufrag,
1345*d9f75844SAndroid Build Coastguard Worker             local_transports[0].description.ice_ufrag);
1346*d9f75844SAndroid Build Coastguard Worker   EXPECT_NE(answer_transports[0].description.ice_pwd,
1347*d9f75844SAndroid Build Coastguard Worker             local_transports[0].description.ice_pwd);
1348*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(answer_transports[1].description.ice_ufrag,
1349*d9f75844SAndroid Build Coastguard Worker             local_transports[1].description.ice_ufrag);
1350*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(answer_transports[1].description.ice_pwd,
1351*d9f75844SAndroid Build Coastguard Worker             local_transports[1].description.ice_pwd);
1352*d9f75844SAndroid Build Coastguard Worker }
1353*d9f75844SAndroid Build Coastguard Worker 
1354*d9f75844SAndroid Build Coastguard Worker // Test that when the initial offerer (caller) uses the lite implementation of
1355*d9f75844SAndroid Build Coastguard Worker // ICE and the callee uses the full implementation, the caller takes the
1356*d9f75844SAndroid Build Coastguard Worker // CONTROLLED role and the callee takes the CONTROLLING role. This is specified
1357*d9f75844SAndroid Build Coastguard Worker // in RFC5245 Section 5.1.1.
TEST_P(PeerConnectionIceTest,OfferFromLiteIceControlledAndAnswerFromFullIceControlling)1358*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
1359*d9f75844SAndroid Build Coastguard Worker        OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
1360*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1361*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1362*d9f75844SAndroid Build Coastguard Worker 
1363*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1364*d9f75844SAndroid Build Coastguard Worker   SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1365*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1366*d9f75844SAndroid Build Coastguard Worker       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1367*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1368*d9f75844SAndroid Build Coastguard Worker 
1369*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1370*d9f75844SAndroid Build Coastguard Worker   SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
1371*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1372*d9f75844SAndroid Build Coastguard Worker       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1373*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1374*d9f75844SAndroid Build Coastguard Worker 
1375*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
1376*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
1377*d9f75844SAndroid Build Coastguard Worker }
1378*d9f75844SAndroid Build Coastguard Worker 
1379*d9f75844SAndroid Build Coastguard Worker // Test that when the caller and the callee both use the lite implementation of
1380*d9f75844SAndroid Build Coastguard Worker // ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
1381*d9f75844SAndroid Build Coastguard Worker // takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
TEST_P(PeerConnectionIceTest,OfferFromLiteIceControllingAndAnswerFromLiteIceControlled)1382*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest,
1383*d9f75844SAndroid Build Coastguard Worker        OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
1384*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1385*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1386*d9f75844SAndroid Build Coastguard Worker 
1387*d9f75844SAndroid Build Coastguard Worker   auto offer = caller->CreateOffer();
1388*d9f75844SAndroid Build Coastguard Worker   SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1389*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1390*d9f75844SAndroid Build Coastguard Worker       caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1391*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1392*d9f75844SAndroid Build Coastguard Worker 
1393*d9f75844SAndroid Build Coastguard Worker   auto answer = callee->CreateAnswer();
1394*d9f75844SAndroid Build Coastguard Worker   SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
1395*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1396*d9f75844SAndroid Build Coastguard Worker       callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1397*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1398*d9f75844SAndroid Build Coastguard Worker 
1399*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
1400*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
1401*d9f75844SAndroid Build Coastguard Worker }
1402*d9f75844SAndroid Build Coastguard Worker 
1403*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(PeerConnectionIceTest,
1404*d9f75844SAndroid Build Coastguard Worker                          PeerConnectionIceTest,
1405*d9f75844SAndroid Build Coastguard Worker                          Values(SdpSemantics::kPlanB_DEPRECATED,
1406*d9f75844SAndroid Build Coastguard Worker                                 SdpSemantics::kUnifiedPlan));
1407*d9f75844SAndroid Build Coastguard Worker 
1408*d9f75844SAndroid Build Coastguard Worker class PeerConnectionIceConfigTest : public ::testing::Test {
1409*d9f75844SAndroid Build Coastguard Worker  public:
PeerConnectionIceConfigTest()1410*d9f75844SAndroid Build Coastguard Worker   PeerConnectionIceConfigTest()
1411*d9f75844SAndroid Build Coastguard Worker       : socket_server_(rtc::CreateDefaultSocketServer()),
1412*d9f75844SAndroid Build Coastguard Worker         main_thread_(socket_server_.get()) {}
1413*d9f75844SAndroid Build Coastguard Worker 
1414*d9f75844SAndroid Build Coastguard Worker  protected:
SetUp()1415*d9f75844SAndroid Build Coastguard Worker   void SetUp() override {
1416*d9f75844SAndroid Build Coastguard Worker     pc_factory_ = CreatePeerConnectionFactory(
1417*d9f75844SAndroid Build Coastguard Worker         rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
1418*d9f75844SAndroid Build Coastguard Worker         FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
1419*d9f75844SAndroid Build Coastguard Worker         CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
1420*d9f75844SAndroid Build Coastguard Worker         CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
1421*d9f75844SAndroid Build Coastguard Worker         nullptr /* audio_processing */);
1422*d9f75844SAndroid Build Coastguard Worker   }
CreatePeerConnection(const RTCConfiguration & config)1423*d9f75844SAndroid Build Coastguard Worker   void CreatePeerConnection(const RTCConfiguration& config) {
1424*d9f75844SAndroid Build Coastguard Worker     packet_socket_factory_.reset(
1425*d9f75844SAndroid Build Coastguard Worker         new rtc::BasicPacketSocketFactory(socket_server_.get()));
1426*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<cricket::FakePortAllocator> port_allocator(
1427*d9f75844SAndroid Build Coastguard Worker         new cricket::FakePortAllocator(rtc::Thread::Current(),
1428*d9f75844SAndroid Build Coastguard Worker                                        packet_socket_factory_.get()));
1429*d9f75844SAndroid Build Coastguard Worker     port_allocator_ = port_allocator.get();
1430*d9f75844SAndroid Build Coastguard Worker     port_allocator_->SetIceTiebreaker(kTiebreakerDefault);
1431*d9f75844SAndroid Build Coastguard Worker     PeerConnectionDependencies pc_dependencies(&observer_);
1432*d9f75844SAndroid Build Coastguard Worker     pc_dependencies.allocator = std::move(port_allocator);
1433*d9f75844SAndroid Build Coastguard Worker     auto result = pc_factory_->CreatePeerConnectionOrError(
1434*d9f75844SAndroid Build Coastguard Worker         config, std::move(pc_dependencies));
1435*d9f75844SAndroid Build Coastguard Worker     EXPECT_TRUE(result.ok());
1436*d9f75844SAndroid Build Coastguard Worker     pc_ = result.MoveValue();
1437*d9f75844SAndroid Build Coastguard Worker   }
1438*d9f75844SAndroid Build Coastguard Worker 
1439*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::SocketServer> socket_server_;
1440*d9f75844SAndroid Build Coastguard Worker   rtc::AutoSocketServerThread main_thread_;
1441*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
1442*d9f75844SAndroid Build Coastguard Worker   rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
1443*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<rtc::PacketSocketFactory> packet_socket_factory_;
1444*d9f75844SAndroid Build Coastguard Worker   cricket::FakePortAllocator* port_allocator_ = nullptr;
1445*d9f75844SAndroid Build Coastguard Worker 
1446*d9f75844SAndroid Build Coastguard Worker   MockPeerConnectionObserver observer_;
1447*d9f75844SAndroid Build Coastguard Worker };
1448*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceConfigTest,SetStunCandidateKeepaliveInterval)1449*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
1450*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1451*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1452*d9f75844SAndroid Build Coastguard Worker   config.stun_candidate_keepalive_interval = 123;
1453*d9f75844SAndroid Build Coastguard Worker   config.ice_candidate_pool_size = 1;
1454*d9f75844SAndroid Build Coastguard Worker   CreatePeerConnection(config);
1455*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(port_allocator_, nullptr);
1456*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> actual_stun_keepalive_interval =
1457*d9f75844SAndroid Build Coastguard Worker       port_allocator_->stun_candidate_keepalive_interval();
1458*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1459*d9f75844SAndroid Build Coastguard Worker   config.stun_candidate_keepalive_interval = 321;
1460*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(pc_->SetConfiguration(config).ok());
1461*d9f75844SAndroid Build Coastguard Worker   actual_stun_keepalive_interval =
1462*d9f75844SAndroid Build Coastguard Worker       port_allocator_->stun_candidate_keepalive_interval();
1463*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1464*d9f75844SAndroid Build Coastguard Worker }
1465*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceConfigTest,SetStableWritableConnectionInterval)1466*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceConfigTest, SetStableWritableConnectionInterval) {
1467*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1468*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1469*d9f75844SAndroid Build Coastguard Worker   config.stable_writable_connection_ping_interval_ms = 3500;
1470*d9f75844SAndroid Build Coastguard Worker   CreatePeerConnection(config);
1471*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(pc_->SetConfiguration(config).ok());
1472*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(pc_->GetConfiguration().stable_writable_connection_ping_interval_ms,
1473*d9f75844SAndroid Build Coastguard Worker             config.stable_writable_connection_ping_interval_ms);
1474*d9f75844SAndroid Build Coastguard Worker }
1475*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceConfigTest,SetStableWritableConnectionInterval_FailsValidation)1476*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceConfigTest,
1477*d9f75844SAndroid Build Coastguard Worker        SetStableWritableConnectionInterval_FailsValidation) {
1478*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1479*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1480*d9f75844SAndroid Build Coastguard Worker   CreatePeerConnection(config);
1481*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(pc_->SetConfiguration(config).ok());
1482*d9f75844SAndroid Build Coastguard Worker   config.stable_writable_connection_ping_interval_ms = 5000;
1483*d9f75844SAndroid Build Coastguard Worker   config.ice_check_interval_strong_connectivity = 7500;
1484*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(pc_->SetConfiguration(config).ok());
1485*d9f75844SAndroid Build Coastguard Worker }
1486*d9f75844SAndroid Build Coastguard Worker 
TEST_F(PeerConnectionIceConfigTest,SetStableWritableConnectionInterval_DefaultValue_FailsValidation)1487*d9f75844SAndroid Build Coastguard Worker TEST_F(PeerConnectionIceConfigTest,
1488*d9f75844SAndroid Build Coastguard Worker        SetStableWritableConnectionInterval_DefaultValue_FailsValidation) {
1489*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1490*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1491*d9f75844SAndroid Build Coastguard Worker   CreatePeerConnection(config);
1492*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(pc_->SetConfiguration(config).ok());
1493*d9f75844SAndroid Build Coastguard Worker   config.ice_check_interval_strong_connectivity = 2500;
1494*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(pc_->SetConfiguration(config).ok());
1495*d9f75844SAndroid Build Coastguard Worker   config.ice_check_interval_strong_connectivity = 2501;
1496*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(pc_->SetConfiguration(config).ok());
1497*d9f75844SAndroid Build Coastguard Worker }
1498*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,IceCredentialsCreateOffer)1499*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, IceCredentialsCreateOffer) {
1500*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1501*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1502*d9f75844SAndroid Build Coastguard Worker   config.ice_candidate_pool_size = 1;
1503*d9f75844SAndroid Build Coastguard Worker   auto pc = CreatePeerConnectionWithAudioVideo(config);
1504*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(pc->port_allocator_, nullptr);
1505*d9f75844SAndroid Build Coastguard Worker   auto offer = pc->CreateOffer();
1506*d9f75844SAndroid Build Coastguard Worker   auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1507*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, credentials.size());
1508*d9f75844SAndroid Build Coastguard Worker 
1509*d9f75844SAndroid Build Coastguard Worker   auto* desc = offer->description();
1510*d9f75844SAndroid Build Coastguard Worker   for (const auto& content : desc->contents()) {
1511*d9f75844SAndroid Build Coastguard Worker     auto* transport_info = desc->GetTransportInfoByName(content.name);
1512*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1513*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1514*d9f75844SAndroid Build Coastguard Worker   }
1515*d9f75844SAndroid Build Coastguard Worker }
1516*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,IceCredentialsCreateAnswer)1517*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, IceCredentialsCreateAnswer) {
1518*d9f75844SAndroid Build Coastguard Worker   RTCConfiguration config;
1519*d9f75844SAndroid Build Coastguard Worker   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
1520*d9f75844SAndroid Build Coastguard Worker   config.ice_candidate_pool_size = 1;
1521*d9f75844SAndroid Build Coastguard Worker   auto pc = CreatePeerConnectionWithAudioVideo(config);
1522*d9f75844SAndroid Build Coastguard Worker   ASSERT_NE(pc->port_allocator_, nullptr);
1523*d9f75844SAndroid Build Coastguard Worker   auto offer = pc->CreateOffer();
1524*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(pc->SetRemoteDescription(std::move(offer)));
1525*d9f75844SAndroid Build Coastguard Worker   auto answer = pc->CreateAnswer();
1526*d9f75844SAndroid Build Coastguard Worker 
1527*d9f75844SAndroid Build Coastguard Worker   auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1528*d9f75844SAndroid Build Coastguard Worker   ASSERT_EQ(1u, credentials.size());
1529*d9f75844SAndroid Build Coastguard Worker 
1530*d9f75844SAndroid Build Coastguard Worker   auto* desc = answer->description();
1531*d9f75844SAndroid Build Coastguard Worker   for (const auto& content : desc->contents()) {
1532*d9f75844SAndroid Build Coastguard Worker     auto* transport_info = desc->GetTransportInfoByName(content.name);
1533*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1534*d9f75844SAndroid Build Coastguard Worker     EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1535*d9f75844SAndroid Build Coastguard Worker   }
1536*d9f75844SAndroid Build Coastguard Worker }
1537*d9f75844SAndroid Build Coastguard Worker 
1538*d9f75844SAndroid Build Coastguard Worker // Regression test for https://bugs.chromium.org/p/webrtc/issues/detail?id=4728
TEST_P(PeerConnectionIceTest,CloseDoesNotTransitionGatheringStateToComplete)1539*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, CloseDoesNotTransitionGatheringStateToComplete) {
1540*d9f75844SAndroid Build Coastguard Worker   auto pc = CreatePeerConnectionWithAudioVideo();
1541*d9f75844SAndroid Build Coastguard Worker   pc->pc()->Close();
1542*d9f75844SAndroid Build Coastguard Worker   EXPECT_FALSE(pc->IsIceGatheringDone());
1543*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1544*d9f75844SAndroid Build Coastguard Worker             pc->pc()->ice_gathering_state());
1545*d9f75844SAndroid Build Coastguard Worker }
1546*d9f75844SAndroid Build Coastguard Worker 
TEST_P(PeerConnectionIceTest,PrefersMidOverMLineIndex)1547*d9f75844SAndroid Build Coastguard Worker TEST_P(PeerConnectionIceTest, PrefersMidOverMLineIndex) {
1548*d9f75844SAndroid Build Coastguard Worker   const SocketAddress kCalleeAddress("1.1.1.1", 1111);
1549*d9f75844SAndroid Build Coastguard Worker 
1550*d9f75844SAndroid Build Coastguard Worker   auto caller = CreatePeerConnectionWithAudioVideo();
1551*d9f75844SAndroid Build Coastguard Worker   auto callee = CreatePeerConnectionWithAudioVideo();
1552*d9f75844SAndroid Build Coastguard Worker 
1553*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1554*d9f75844SAndroid Build Coastguard Worker   ASSERT_TRUE(
1555*d9f75844SAndroid Build Coastguard Worker       caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1556*d9f75844SAndroid Build Coastguard Worker 
1557*d9f75844SAndroid Build Coastguard Worker   // `candidate.transport_name()` is empty.
1558*d9f75844SAndroid Build Coastguard Worker   cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
1559*d9f75844SAndroid Build Coastguard Worker   auto* audio_content = cricket::GetFirstAudioContent(
1560*d9f75844SAndroid Build Coastguard Worker       caller->pc()->local_description()->description());
1561*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceCandidateInterface> ice_candidate =
1562*d9f75844SAndroid Build Coastguard Worker       CreateIceCandidate(audio_content->name, 65535, candidate);
1563*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
1564*d9f75844SAndroid Build Coastguard Worker   EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
1565*d9f75844SAndroid Build Coastguard Worker }
1566*d9f75844SAndroid Build Coastguard Worker 
1567*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
1568