blob: 0ca4be2832344d1fde55303292f92db0eac96bd9 [file] [log] [blame]
Steve Antonf1c6db12017-10-13 11:13:35 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "p2p/base/fake_port_allocator.h"
12#include "p2p/base/test_stun_server.h"
13#include "p2p/client/basic_port_allocator.h"
14#include "pc/media_session.h"
15#include "pc/peer_connection.h"
16#include "pc/peer_connection_wrapper.h"
17#include "pc/sdp_utils.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070018#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080019#include "pc/test/android_test_initializer.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070020#endif
Karl Wiberg918f50c2018-07-05 11:40:33 +020021#include "absl/memory/memory.h"
Karl Wiberg1b0eae32017-10-17 14:48:54 +020022#include "api/audio_codecs/builtin_audio_decoder_factory.h"
23#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010024#include "api/create_peerconnection_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "api/peer_connection_proxy.h"
26#include "api/uma_metrics.h"
Anders Carlsson67537952018-05-03 11:28:29 +020027#include "api/video_codecs/builtin_video_decoder_factory.h"
28#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080029#include "pc/test/fake_audio_capture_module.h"
30#include "rtc_base/fake_network.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070031#include "rtc_base/gunit.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020032#include "rtc_base/strings/string_builder.h"
Steve Anton10542f22019-01-11 09:11:00 -080033#include "rtc_base/virtual_socket_server.h"
Mirko Bonadei17f48782018-09-28 08:51:10 +020034#include "system_wrappers/include/metrics.h"
Steve Antonb443dfe2019-03-05 14:09:49 -080035#include "test/gmock.h"
Steve Antonf1c6db12017-10-13 11:13:35 -070036
37namespace webrtc {
38
39using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
40using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
41using rtc::SocketAddress;
Steve Anton46d926a2018-01-23 10:23:06 -080042using ::testing::Combine;
Steve Antonb443dfe2019-03-05 14:09:49 -080043using ::testing::ElementsAre;
44using ::testing::Pair;
Steve Antonf1c6db12017-10-13 11:13:35 -070045using ::testing::Values;
46
47constexpr int kIceCandidatesTimeout = 10000;
48
Steve Anton46d926a2018-01-23 10:23:06 -080049class PeerConnectionWrapperForIceTest : public PeerConnectionWrapper {
Steve Antonf1c6db12017-10-13 11:13:35 -070050 public:
51 using PeerConnectionWrapper::PeerConnectionWrapper;
52
53 // Adds a new ICE candidate to the first transport.
54 bool AddIceCandidate(cricket::Candidate* candidate) {
55 RTC_DCHECK(pc()->remote_description());
56 const auto* desc = pc()->remote_description()->description();
57 RTC_DCHECK(desc->contents().size() > 0);
58 const auto& first_content = desc->contents()[0];
59 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -070060 std::unique_ptr<IceCandidateInterface> jsep_candidate =
Guido Urdaneta41633172019-05-23 20:12:29 +020061 CreateIceCandidate(first_content.name, -1, *candidate);
Steve Anton27ab0e52018-07-23 15:11:53 -070062 return pc()->AddIceCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -070063 }
64
65 // Returns ICE candidates from the remote session description.
66 std::vector<const IceCandidateInterface*>
67 GetIceCandidatesFromRemoteDescription() {
68 const SessionDescriptionInterface* sdesc = pc()->remote_description();
69 RTC_DCHECK(sdesc);
70 std::vector<const IceCandidateInterface*> candidates;
71 for (size_t mline_index = 0; mline_index < sdesc->number_of_mediasections();
72 mline_index++) {
73 const auto* candidate_collection = sdesc->candidates(mline_index);
74 for (size_t i = 0; i < candidate_collection->count(); i++) {
75 candidates.push_back(candidate_collection->at(i));
76 }
77 }
78 return candidates;
79 }
80
81 rtc::FakeNetworkManager* network() { return network_; }
82
83 void set_network(rtc::FakeNetworkManager* network) { network_ = network; }
84
Jonas Oreland1cd39fa2018-10-11 07:47:12 +020085 // The port allocator used by this PC.
86 cricket::PortAllocator* port_allocator_;
87
Steve Antonf1c6db12017-10-13 11:13:35 -070088 private:
89 rtc::FakeNetworkManager* network_;
90};
91
Steve Anton46d926a2018-01-23 10:23:06 -080092class PeerConnectionIceBaseTest : public ::testing::Test {
Steve Antonf1c6db12017-10-13 11:13:35 -070093 protected:
Steve Anton46d926a2018-01-23 10:23:06 -080094 typedef std::unique_ptr<PeerConnectionWrapperForIceTest> WrapperPtr;
Steve Antonf1c6db12017-10-13 11:13:35 -070095
Steve Anton46d926a2018-01-23 10:23:06 -080096 explicit PeerConnectionIceBaseTest(SdpSemantics sdp_semantics)
97 : vss_(new rtc::VirtualSocketServer()),
98 main_(vss_.get()),
99 sdp_semantics_(sdp_semantics) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700100#ifdef WEBRTC_ANDROID
101 InitializeAndroidObjects();
102#endif
103 pc_factory_ = CreatePeerConnectionFactory(
104 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200105 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
106 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
107 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
108 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Antonf1c6db12017-10-13 11:13:35 -0700109 }
110
111 WrapperPtr CreatePeerConnection() {
112 return CreatePeerConnection(RTCConfiguration());
113 }
114
115 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
116 auto* fake_network = NewFakeNetwork();
117 auto port_allocator =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200118 absl::make_unique<cricket::BasicPortAllocator>(fake_network);
Steve Antonf1c6db12017-10-13 11:13:35 -0700119 port_allocator->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
120 cricket::PORTALLOCATOR_DISABLE_RELAY);
121 port_allocator->set_step_delay(cricket::kMinimumStepDelay);
Steve Anton46d926a2018-01-23 10:23:06 -0800122 RTCConfiguration modified_config = config;
123 modified_config.sdp_semantics = sdp_semantics_;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200124 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200125 auto port_allocator_copy = port_allocator.get();
Steve Antonf1c6db12017-10-13 11:13:35 -0700126 auto pc = pc_factory_->CreatePeerConnection(
Steve Anton46d926a2018-01-23 10:23:06 -0800127 modified_config, std::move(port_allocator), nullptr, observer.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700128 if (!pc) {
129 return nullptr;
130 }
131
Yves Gerey4e933292018-10-31 15:36:05 +0100132 observer->SetPeerConnectionInterface(pc.get());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200133 auto wrapper = absl::make_unique<PeerConnectionWrapperForIceTest>(
Steve Antonf1c6db12017-10-13 11:13:35 -0700134 pc_factory_, pc, std::move(observer));
135 wrapper->set_network(fake_network);
Jonas Oreland1cd39fa2018-10-11 07:47:12 +0200136 wrapper->port_allocator_ = port_allocator_copy;
Steve Antonf1c6db12017-10-13 11:13:35 -0700137 return wrapper;
138 }
139
140 // Accepts the same arguments as CreatePeerConnection and adds default audio
141 // and video tracks.
142 template <typename... Args>
143 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
144 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
145 if (!wrapper) {
146 return nullptr;
147 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700148 wrapper->AddAudioTrack("a");
149 wrapper->AddVideoTrack("v");
Steve Antonf1c6db12017-10-13 11:13:35 -0700150 return wrapper;
151 }
152
153 cricket::Candidate CreateLocalUdpCandidate(
154 const rtc::SocketAddress& address) {
155 cricket::Candidate candidate;
156 candidate.set_component(cricket::ICE_CANDIDATE_COMPONENT_DEFAULT);
157 candidate.set_protocol(cricket::UDP_PROTOCOL_NAME);
158 candidate.set_address(address);
159 candidate.set_type(cricket::LOCAL_PORT_TYPE);
160 return candidate;
161 }
162
163 // Remove all ICE ufrag/pwd lines from the given session description.
164 void RemoveIceUfragPwd(SessionDescriptionInterface* sdesc) {
165 SetIceUfragPwd(sdesc, "", "");
166 }
167
168 // Sets all ICE ufrag/pwds on the given session description.
169 void SetIceUfragPwd(SessionDescriptionInterface* sdesc,
170 const std::string& ufrag,
171 const std::string& pwd) {
172 auto* desc = sdesc->description();
173 for (const auto& content : desc->contents()) {
174 auto* transport_info = desc->GetTransportInfoByName(content.name);
175 transport_info->description.ice_ufrag = ufrag;
176 transport_info->description.ice_pwd = pwd;
177 }
178 }
179
Qingsi Wange1692722017-11-29 13:27:20 -0800180 // Set ICE mode on the given session description.
181 void SetIceMode(SessionDescriptionInterface* sdesc,
182 const cricket::IceMode ice_mode) {
183 auto* desc = sdesc->description();
184 for (const auto& content : desc->contents()) {
185 auto* transport_info = desc->GetTransportInfoByName(content.name);
186 transport_info->description.ice_mode = ice_mode;
187 }
188 }
189
Steve Antonf1c6db12017-10-13 11:13:35 -0700190 cricket::TransportDescription* GetFirstTransportDescription(
191 SessionDescriptionInterface* sdesc) {
192 auto* desc = sdesc->description();
193 RTC_DCHECK(desc->contents().size() > 0);
194 auto* transport_info =
195 desc->GetTransportInfoByName(desc->contents()[0].name);
196 RTC_DCHECK(transport_info);
197 return &transport_info->description;
198 }
199
200 const cricket::TransportDescription* GetFirstTransportDescription(
201 const SessionDescriptionInterface* sdesc) {
202 auto* desc = sdesc->description();
203 RTC_DCHECK(desc->contents().size() > 0);
204 auto* transport_info =
205 desc->GetTransportInfoByName(desc->contents()[0].name);
206 RTC_DCHECK(transport_info);
207 return &transport_info->description;
208 }
209
Qingsi Wange1692722017-11-29 13:27:20 -0800210 // TODO(qingsi): Rewrite this method in terms of the standard IceTransport
211 // after it is implemented.
212 cricket::IceRole GetIceRole(const WrapperPtr& pc_wrapper_ptr) {
Mirko Bonadeie97de912017-12-13 11:29:34 +0100213 auto* pc_proxy =
214 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
215 pc_wrapper_ptr->pc());
216 PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
Mirko Bonadei739baf02019-01-27 17:29:42 +0100217 for (const auto& transceiver : pc->GetTransceiversInternal()) {
Steve Anton69470252018-02-09 11:43:08 -0800218 if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
Bjorn A Mellem3a1b9272019-05-24 16:13:08 -0700219 auto dtls_transport = pc->LookupDtlsTransportByMidInternal(
220 transceiver->internal()->channel()->content_name());
221 return dtls_transport->ice_transport()->internal()->GetIceRole();
Steve Anton46d926a2018-01-23 10:23:06 -0800222 }
223 }
224 RTC_NOTREACHED();
225 return cricket::ICEROLE_UNKNOWN;
Qingsi Wange1692722017-11-29 13:27:20 -0800226 }
227
Henrik Boström79b69802019-07-18 11:16:56 +0200228 // Returns a list of (ufrag, pwd) pairs in the order that they appear in
229 // |description|, or the empty list if |description| is null.
230 std::vector<std::pair<std::string, std::string>> GetIceCredentials(
231 const SessionDescriptionInterface* description) {
232 std::vector<std::pair<std::string, std::string>> ice_credentials;
233 if (!description)
234 return ice_credentials;
235 const auto* desc = description->description();
236 for (const auto& content_info : desc->contents()) {
237 const auto* transport_info =
238 desc->GetTransportInfoByName(content_info.name);
239 if (transport_info) {
240 ice_credentials.push_back(
241 std::make_pair(transport_info->description.ice_ufrag,
242 transport_info->description.ice_pwd));
243 }
244 }
245 return ice_credentials;
246 }
247
Steve Antonf1c6db12017-10-13 11:13:35 -0700248 bool AddCandidateToFirstTransport(cricket::Candidate* candidate,
249 SessionDescriptionInterface* sdesc) {
250 auto* desc = sdesc->description();
251 RTC_DCHECK(desc->contents().size() > 0);
252 const auto& first_content = desc->contents()[0];
253 candidate->set_transport_name(first_content.name);
Steve Anton27ab0e52018-07-23 15:11:53 -0700254 std::unique_ptr<IceCandidateInterface> jsep_candidate =
255 CreateIceCandidate(first_content.name, 0, *candidate);
256 return sdesc->AddCandidate(jsep_candidate.get());
Steve Antonf1c6db12017-10-13 11:13:35 -0700257 }
258
259 rtc::FakeNetworkManager* NewFakeNetwork() {
260 // The PeerConnection's port allocator is tied to the PeerConnection's
261 // lifetime and expects the underlying NetworkManager to outlive it. That
262 // prevents us from having the PeerConnectionWrapper own the fake network.
263 // Therefore, the test fixture will own all the fake networks even though
264 // tests should access the fake network through the PeerConnectionWrapper.
265 auto* fake_network = new rtc::FakeNetworkManager();
266 fake_networks_.emplace_back(fake_network);
267 return fake_network;
268 }
269
270 std::unique_ptr<rtc::VirtualSocketServer> vss_;
271 rtc::AutoSocketServerThread main_;
272 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
273 std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
Steve Anton46d926a2018-01-23 10:23:06 -0800274 const SdpSemantics sdp_semantics_;
275};
276
277class PeerConnectionIceTest
278 : public PeerConnectionIceBaseTest,
279 public ::testing::WithParamInterface<SdpSemantics> {
280 protected:
Harald Alvestrand76829d72018-07-18 23:24:36 +0200281 PeerConnectionIceTest() : PeerConnectionIceBaseTest(GetParam()) {
282 webrtc::metrics::Reset();
283 }
Steve Antonf1c6db12017-10-13 11:13:35 -0700284};
285
286::testing::AssertionResult AssertCandidatesEqual(const char* a_expr,
287 const char* b_expr,
288 const cricket::Candidate& a,
289 const cricket::Candidate& b) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200290 rtc::StringBuilder failure_info;
Steve Antonf1c6db12017-10-13 11:13:35 -0700291 if (a.component() != b.component()) {
292 failure_info << "\ncomponent: " << a.component() << " != " << b.component();
293 }
294 if (a.protocol() != b.protocol()) {
295 failure_info << "\nprotocol: " << a.protocol() << " != " << b.protocol();
296 }
297 if (a.address() != b.address()) {
298 failure_info << "\naddress: " << a.address().ToString()
299 << " != " << b.address().ToString();
300 }
301 if (a.type() != b.type()) {
302 failure_info << "\ntype: " << a.type() << " != " << b.type();
303 }
304 std::string failure_info_str = failure_info.str();
305 if (failure_info_str.empty()) {
306 return ::testing::AssertionSuccess();
307 } else {
308 return ::testing::AssertionFailure()
309 << a_expr << " and " << b_expr << " are not equal"
310 << failure_info_str;
311 }
312}
313
Steve Anton46d926a2018-01-23 10:23:06 -0800314TEST_P(PeerConnectionIceTest, OfferContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700315 const SocketAddress kLocalAddress("1.1.1.1", 0);
316
317 auto caller = CreatePeerConnectionWithAudioVideo();
318 caller->network()->AddInterface(kLocalAddress);
319
320 // Start ICE candidate gathering by setting the local offer.
321 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
322
323 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
324
325 auto offer = caller->CreateOffer();
326 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
327 EXPECT_EQ(caller->observer()->GetCandidatesByMline(0).size(),
328 offer->candidates(0)->count());
329 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
330 EXPECT_EQ(caller->observer()->GetCandidatesByMline(1).size(),
331 offer->candidates(1)->count());
332}
333
Steve Anton46d926a2018-01-23 10:23:06 -0800334TEST_P(PeerConnectionIceTest, AnswerContainsGatheredCandidates) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700335 const SocketAddress kCallerAddress("1.1.1.1", 0);
336
337 auto caller = CreatePeerConnectionWithAudioVideo();
338 auto callee = CreatePeerConnectionWithAudioVideo();
339 caller->network()->AddInterface(kCallerAddress);
340
341 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
342 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
343
344 EXPECT_TRUE_WAIT(callee->IsIceGatheringDone(), kIceCandidatesTimeout);
345
Steve Antondffead82018-02-06 10:31:29 -0800346 auto* answer = callee->pc()->local_description();
Steve Antonf1c6db12017-10-13 11:13:35 -0700347 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(0).size());
348 EXPECT_EQ(callee->observer()->GetCandidatesByMline(0).size(),
349 answer->candidates(0)->count());
350 EXPECT_LT(0u, caller->observer()->GetCandidatesByMline(1).size());
351 EXPECT_EQ(callee->observer()->GetCandidatesByMline(1).size(),
352 answer->candidates(1)->count());
353}
354
Steve Anton46d926a2018-01-23 10:23:06 -0800355TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700356 CanSetRemoteSessionDescriptionWithRemoteCandidates) {
357 const SocketAddress kCallerAddress("1.1.1.1", 1111);
358
359 auto caller = CreatePeerConnectionWithAudioVideo();
360 auto callee = CreatePeerConnectionWithAudioVideo();
361
362 auto offer = caller->CreateOfferAndSetAsLocal();
363 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
364 AddCandidateToFirstTransport(&candidate, offer.get());
365
366 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
367 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
368 ASSERT_EQ(1u, remote_candidates.size());
369 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
370 remote_candidates[0]->candidate());
371}
372
Steve Anton46d926a2018-01-23 10:23:06 -0800373TEST_P(PeerConnectionIceTest, SetLocalDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700374 auto caller = CreatePeerConnectionWithAudioVideo();
375
376 auto offer = caller->CreateOffer();
377 RemoveIceUfragPwd(offer.get());
378
379 EXPECT_FALSE(caller->SetLocalDescription(std::move(offer)));
380}
381
Steve Anton46d926a2018-01-23 10:23:06 -0800382TEST_P(PeerConnectionIceTest, SetRemoteDescriptionFailsIfNoIceCredentials) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700383 auto caller = CreatePeerConnectionWithAudioVideo();
384 auto callee = CreatePeerConnectionWithAudioVideo();
385
386 auto offer = caller->CreateOfferAndSetAsLocal();
387 RemoveIceUfragPwd(offer.get());
388
389 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer)));
390}
391
Steve Antonf764cf42018-05-01 14:32:17 -0700392// Test that doing an offer/answer exchange with no transport (i.e., no data
393// channel or media) results in the ICE connection state staying at New.
394TEST_P(PeerConnectionIceTest,
395 OfferAnswerWithNoTransportsDoesNotChangeIceConnectionState) {
396 auto caller = CreatePeerConnection();
397 auto callee = CreatePeerConnection();
398
399 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
400
401 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
402 caller->pc()->ice_connection_state());
403 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
404 callee->pc()->ice_connection_state());
405}
406
Steve Antonf1c6db12017-10-13 11:13:35 -0700407// The following group tests that ICE candidates are not generated before
408// SetLocalDescription is called on a PeerConnection.
409
Steve Anton46d926a2018-01-23 10:23:06 -0800410TEST_P(PeerConnectionIceTest, NoIceCandidatesBeforeSetLocalDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700411 const SocketAddress kLocalAddress("1.1.1.1", 0);
412
413 auto caller = CreatePeerConnectionWithAudioVideo();
414 caller->network()->AddInterface(kLocalAddress);
415
416 // Pump for 1 second and verify that no candidates are generated.
417 rtc::Thread::Current()->ProcessMessages(1000);
418
419 EXPECT_EQ(0u, caller->observer()->candidates_.size());
420}
Steve Anton46d926a2018-01-23 10:23:06 -0800421TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700422 NoIceCandidatesBeforeAnswerSetAsLocalDescription) {
423 const SocketAddress kCallerAddress("1.1.1.1", 1111);
424
425 auto caller = CreatePeerConnectionWithAudioVideo();
426 auto callee = CreatePeerConnectionWithAudioVideo();
427 caller->network()->AddInterface(kCallerAddress);
428
429 auto offer = caller->CreateOfferAndSetAsLocal();
430 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
431 AddCandidateToFirstTransport(&candidate, offer.get());
432 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
433
434 // Pump for 1 second and verify that no candidates are generated.
435 rtc::Thread::Current()->ProcessMessages(1000);
436
437 EXPECT_EQ(0u, callee->observer()->candidates_.size());
438}
439
Steve Anton46d926a2018-01-23 10:23:06 -0800440TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenRemoteDescriptionNotSet) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700441 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
442
443 auto caller = CreatePeerConnectionWithAudioVideo();
444 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton27ab0e52018-07-23 15:11:53 -0700445 std::unique_ptr<IceCandidateInterface> jsep_candidate =
446 CreateIceCandidate(cricket::CN_AUDIO, 0, candidate);
Steve Antonf1c6db12017-10-13 11:13:35 -0700447
Steve Anton27ab0e52018-07-23 15:11:53 -0700448 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700449
450 caller->CreateOfferAndSetAsLocal();
451
Steve Anton27ab0e52018-07-23 15:11:53 -0700452 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonb443dfe2019-03-05 14:09:49 -0800453 EXPECT_THAT(webrtc::metrics::Samples("WebRTC.PeerConnection.AddIceCandidate"),
454 ElementsAre(Pair(kAddIceCandidateFailNoRemoteDescription, 2)));
Steve Antonf1c6db12017-10-13 11:13:35 -0700455}
456
Steve Antonc79268f2018-04-24 09:54:10 -0700457TEST_P(PeerConnectionIceTest, CannotAddCandidateWhenPeerConnectionClosed) {
458 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
459
460 auto caller = CreatePeerConnectionWithAudioVideo();
461 auto callee = CreatePeerConnectionWithAudioVideo();
462
463 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
464
465 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
466 auto* audio_content = cricket::GetFirstAudioContent(
467 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700468 std::unique_ptr<IceCandidateInterface> jsep_candidate =
469 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700470
471 caller->pc()->Close();
472
Steve Anton27ab0e52018-07-23 15:11:53 -0700473 EXPECT_FALSE(caller->pc()->AddIceCandidate(jsep_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700474}
475
Steve Anton46d926a2018-01-23 10:23:06 -0800476TEST_P(PeerConnectionIceTest, DuplicateIceCandidateIgnoredWhenAdded) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700477 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
478
479 auto caller = CreatePeerConnectionWithAudioVideo();
480 auto callee = CreatePeerConnectionWithAudioVideo();
481
482 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
483 ASSERT_TRUE(
484 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
485
486 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
487 caller->AddIceCandidate(&candidate);
488 EXPECT_TRUE(caller->AddIceCandidate(&candidate));
489 EXPECT_EQ(1u, caller->GetIceCandidatesFromRemoteDescription().size());
490}
491
Steve Anton46d926a2018-01-23 10:23:06 -0800492TEST_P(PeerConnectionIceTest,
Steve Antonc79268f2018-04-24 09:54:10 -0700493 CannotRemoveIceCandidatesWhenPeerConnectionClosed) {
494 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
495
496 auto caller = CreatePeerConnectionWithAudioVideo();
497 auto callee = CreatePeerConnectionWithAudioVideo();
498
499 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
500
501 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
502 auto* audio_content = cricket::GetFirstAudioContent(
503 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700504 std::unique_ptr<IceCandidateInterface> ice_candidate =
505 CreateIceCandidate(audio_content->name, 0, candidate);
Steve Antonc79268f2018-04-24 09:54:10 -0700506
Steve Anton27ab0e52018-07-23 15:11:53 -0700507 ASSERT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonc79268f2018-04-24 09:54:10 -0700508
509 caller->pc()->Close();
510
511 EXPECT_FALSE(caller->pc()->RemoveIceCandidates({candidate}));
512}
513
514TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700515 AddRemoveCandidateWithEmptyTransportDoesNotCrash) {
516 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
517
518 auto caller = CreatePeerConnectionWithAudioVideo();
519 auto callee = CreatePeerConnectionWithAudioVideo();
520
521 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
522 ASSERT_TRUE(
523 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
524
525 // |candidate.transport_name()| is empty.
526 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
Steve Anton46d926a2018-01-23 10:23:06 -0800527 auto* audio_content = cricket::GetFirstAudioContent(
528 caller->pc()->local_description()->description());
Steve Anton27ab0e52018-07-23 15:11:53 -0700529 std::unique_ptr<IceCandidateInterface> ice_candidate =
530 CreateIceCandidate(audio_content->name, 0, candidate);
531 EXPECT_TRUE(caller->pc()->AddIceCandidate(ice_candidate.get()));
Steve Antonf1c6db12017-10-13 11:13:35 -0700532 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
533}
534
Steve Anton46d926a2018-01-23 10:23:06 -0800535TEST_P(PeerConnectionIceTest, RemoveCandidateRemovesFromRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700536 const SocketAddress kCalleeAddress("1.1.1.1", 1111);
537
538 auto caller = CreatePeerConnectionWithAudioVideo();
539 auto callee = CreatePeerConnectionWithAudioVideo();
540
541 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
542 ASSERT_TRUE(
543 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
544
545 cricket::Candidate candidate = CreateLocalUdpCandidate(kCalleeAddress);
546 ASSERT_TRUE(caller->AddIceCandidate(&candidate));
547 EXPECT_TRUE(caller->pc()->RemoveIceCandidates({candidate}));
548 EXPECT_EQ(0u, caller->GetIceCandidatesFromRemoteDescription().size());
549}
550
551// Test that if a candidate is added via AddIceCandidate and via an updated
552// remote description, then both candidates appear in the stored remote
553// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800554TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700555 CandidateInSubsequentOfferIsAddedToRemoteDescription) {
556 const SocketAddress kCallerAddress1("1.1.1.1", 1111);
557 const SocketAddress kCallerAddress2("2.2.2.2", 2222);
558
559 auto caller = CreatePeerConnectionWithAudioVideo();
560 auto callee = CreatePeerConnectionWithAudioVideo();
561
562 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
563 ASSERT_TRUE(
564 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
565
566 // Add one candidate via |AddIceCandidate|.
567 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCallerAddress1);
568 ASSERT_TRUE(callee->AddIceCandidate(&candidate1));
569
570 // Add the second candidate via a reoffer.
571 auto offer = caller->CreateOffer();
572 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCallerAddress2);
573 AddCandidateToFirstTransport(&candidate2, offer.get());
574
575 // Expect both candidates to appear in the callee's remote description.
576 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
577 EXPECT_EQ(2u, callee->GetIceCandidatesFromRemoteDescription().size());
578}
579
580// The follow test verifies that SetLocal/RemoteDescription fails when an offer
581// has either ICE ufrag/pwd too short or too long and succeeds otherwise.
582// The standard (https://tools.ietf.org/html/rfc5245#section-15.4) says that
583// pwd must be 22-256 characters and ufrag must be 4-256 characters.
Steve Anton46d926a2018-01-23 10:23:06 -0800584TEST_P(PeerConnectionIceTest, VerifyUfragPwdLength) {
Yves Gerey665174f2018-06-19 15:03:05 +0200585 auto set_local_description_with_ufrag_pwd_length = [this](int ufrag_len,
586 int pwd_len) {
587 auto pc = CreatePeerConnectionWithAudioVideo();
588 auto offer = pc->CreateOffer();
589 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
590 std::string(pwd_len, 'x'));
591 return pc->SetLocalDescription(std::move(offer));
592 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700593
Yves Gerey665174f2018-06-19 15:03:05 +0200594 auto set_remote_description_with_ufrag_pwd_length = [this](int ufrag_len,
595 int pwd_len) {
596 auto pc = CreatePeerConnectionWithAudioVideo();
597 auto offer = pc->CreateOffer();
598 SetIceUfragPwd(offer.get(), std::string(ufrag_len, 'x'),
599 std::string(pwd_len, 'x'));
600 return pc->SetRemoteDescription(std::move(offer));
601 };
Steve Antonf1c6db12017-10-13 11:13:35 -0700602
603 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(3, 22));
604 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(3, 22));
605 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(257, 22));
606 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(257, 22));
607 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 21));
608 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 21));
609 EXPECT_FALSE(set_local_description_with_ufrag_pwd_length(4, 257));
610 EXPECT_FALSE(set_remote_description_with_ufrag_pwd_length(4, 257));
611 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(4, 22));
612 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(4, 22));
613 EXPECT_TRUE(set_local_description_with_ufrag_pwd_length(256, 256));
614 EXPECT_TRUE(set_remote_description_with_ufrag_pwd_length(256, 256));
615}
616
617::testing::AssertionResult AssertIpInCandidates(
618 const char* address_expr,
619 const char* candidates_expr,
620 const SocketAddress& address,
621 const std::vector<IceCandidateInterface*> candidates) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200622 rtc::StringBuilder candidate_hosts;
Steve Antonf1c6db12017-10-13 11:13:35 -0700623 for (const auto* candidate : candidates) {
624 const auto& candidate_ip = candidate->candidate().address().ipaddr();
625 if (candidate_ip == address.ipaddr()) {
626 return ::testing::AssertionSuccess();
627 }
Jonas Olssonabbe8412018-04-03 13:40:05 +0200628 candidate_hosts << "\n" << candidate_ip.ToString();
Steve Antonf1c6db12017-10-13 11:13:35 -0700629 }
630 return ::testing::AssertionFailure()
631 << address_expr << " (host " << address.HostAsURIString()
632 << ") not in " << candidates_expr
633 << " which have the following address hosts:" << candidate_hosts.str();
634}
635
Steve Anton46d926a2018-01-23 10:23:06 -0800636TEST_P(PeerConnectionIceTest, CandidatesGeneratedForEachLocalInterface) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700637 const SocketAddress kLocalAddress1("1.1.1.1", 0);
638 const SocketAddress kLocalAddress2("2.2.2.2", 0);
639
640 auto caller = CreatePeerConnectionWithAudioVideo();
641 caller->network()->AddInterface(kLocalAddress1);
642 caller->network()->AddInterface(kLocalAddress2);
643
644 caller->CreateOfferAndSetAsLocal();
645 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
646
647 auto candidates = caller->observer()->GetCandidatesByMline(0);
648 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress1, candidates);
649 EXPECT_PRED_FORMAT2(AssertIpInCandidates, kLocalAddress2, candidates);
650}
651
Steve Anton46d926a2018-01-23 10:23:06 -0800652TEST_P(PeerConnectionIceTest, TrickledSingleCandidateAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700653 const SocketAddress kCallerAddress("1.1.1.1", 1111);
654
655 auto caller = CreatePeerConnectionWithAudioVideo();
656 auto callee = CreatePeerConnectionWithAudioVideo();
657
658 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
659
660 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
661 callee->AddIceCandidate(&candidate);
662 auto candidates = callee->GetIceCandidatesFromRemoteDescription();
663 ASSERT_EQ(1u, candidates.size());
664 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate,
665 candidates[0]->candidate());
666}
667
Steve Anton46d926a2018-01-23 10:23:06 -0800668TEST_P(PeerConnectionIceTest, TwoTrickledCandidatesAddedToRemoteDescription) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700669 const SocketAddress kCalleeAddress1("1.1.1.1", 1111);
670 const SocketAddress kCalleeAddress2("2.2.2.2", 2222);
671
672 auto caller = CreatePeerConnectionWithAudioVideo();
673 auto callee = CreatePeerConnectionWithAudioVideo();
674
675 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
676 ASSERT_TRUE(
677 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
678
679 cricket::Candidate candidate1 = CreateLocalUdpCandidate(kCalleeAddress1);
680 caller->AddIceCandidate(&candidate1);
681
682 cricket::Candidate candidate2 = CreateLocalUdpCandidate(kCalleeAddress2);
683 caller->AddIceCandidate(&candidate2);
684
685 auto candidates = caller->GetIceCandidatesFromRemoteDescription();
686 ASSERT_EQ(2u, candidates.size());
687 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate1,
688 candidates[0]->candidate());
689 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, candidate2,
690 candidates[1]->candidate());
691}
692
Steve Anton46d926a2018-01-23 10:23:06 -0800693TEST_P(PeerConnectionIceTest, LocalDescriptionUpdatedWhenContinualGathering) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700694 const SocketAddress kLocalAddress("1.1.1.1", 0);
695
696 RTCConfiguration config;
697 config.continual_gathering_policy =
698 PeerConnectionInterface::GATHER_CONTINUALLY;
699 auto caller = CreatePeerConnectionWithAudioVideo(config);
700 caller->network()->AddInterface(kLocalAddress);
701
702 // Start ICE candidate gathering by setting the local offer.
703 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
704
705 // Since we're using continual gathering, we won't get "gathering done".
706 EXPECT_TRUE_WAIT(
707 caller->pc()->local_description()->candidates(0)->count() > 0,
708 kIceCandidatesTimeout);
709}
710
711// Test that when continual gathering is enabled, and a network interface goes
712// down, the candidate is signaled as removed and removed from the local
713// description.
Steve Anton46d926a2018-01-23 10:23:06 -0800714TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700715 LocalCandidatesRemovedWhenNetworkDownIfGatheringContinually) {
716 const SocketAddress kLocalAddress("1.1.1.1", 0);
717
718 RTCConfiguration config;
719 config.continual_gathering_policy =
720 PeerConnectionInterface::GATHER_CONTINUALLY;
721 auto caller = CreatePeerConnectionWithAudioVideo(config);
722 caller->network()->AddInterface(kLocalAddress);
723
724 // Start ICE candidate gathering by setting the local offer.
725 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
726
727 EXPECT_TRUE_WAIT(
728 caller->pc()->local_description()->candidates(0)->count() > 0,
729 kIceCandidatesTimeout);
730
731 // Remove the only network interface, causing the PeerConnection to signal
732 // the removal of all candidates derived from this interface.
733 caller->network()->RemoveInterface(kLocalAddress);
734
735 EXPECT_EQ_WAIT(0u, caller->pc()->local_description()->candidates(0)->count(),
736 kIceCandidatesTimeout);
737 EXPECT_LT(0, caller->observer()->num_candidates_removed_);
738}
739
Steve Anton46d926a2018-01-23 10:23:06 -0800740TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700741 LocalCandidatesNotRemovedWhenNetworkDownIfGatheringOnce) {
742 const SocketAddress kLocalAddress("1.1.1.1", 0);
743
744 RTCConfiguration config;
745 config.continual_gathering_policy = PeerConnectionInterface::GATHER_ONCE;
746 auto caller = CreatePeerConnectionWithAudioVideo(config);
747 caller->network()->AddInterface(kLocalAddress);
748
749 // Start ICE candidate gathering by setting the local offer.
750 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
751
752 EXPECT_TRUE_WAIT(caller->IsIceGatheringDone(), kIceCandidatesTimeout);
753
754 caller->network()->RemoveInterface(kLocalAddress);
755
756 // Verify that the local candidates are not removed;
757 rtc::Thread::Current()->ProcessMessages(1000);
758 EXPECT_EQ(0, caller->observer()->num_candidates_removed_);
759}
760
761// The following group tests that when an offer includes a new ufrag or pwd
762// (indicating an ICE restart) the old candidates are removed and new candidates
763// added to the remote description.
764
Steve Anton46d926a2018-01-23 10:23:06 -0800765TEST_P(PeerConnectionIceTest, IceRestartOfferClearsExistingCandidate) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700766 const SocketAddress kCallerAddress("1.1.1.1", 1111);
767
768 auto caller = CreatePeerConnectionWithAudioVideo();
769 auto callee = CreatePeerConnectionWithAudioVideo();
770
Amit Hilbuchae3df542019-01-07 12:13:08 -0800771 auto offer = caller->CreateOfferAndSetAsLocal();
Steve Antonf1c6db12017-10-13 11:13:35 -0700772 cricket::Candidate candidate = CreateLocalUdpCandidate(kCallerAddress);
773 AddCandidateToFirstTransport(&candidate, offer.get());
774
775 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
776
777 RTCOfferAnswerOptions options;
778 options.ice_restart = true;
Amit Hilbuchae3df542019-01-07 12:13:08 -0800779 ASSERT_TRUE(
780 callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal(options)));
Steve Antonf1c6db12017-10-13 11:13:35 -0700781
782 EXPECT_EQ(0u, callee->GetIceCandidatesFromRemoteDescription().size());
783}
Steve Anton46d926a2018-01-23 10:23:06 -0800784TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -0700785 IceRestartOfferCandidateReplacesExistingCandidate) {
786 const SocketAddress kFirstCallerAddress("1.1.1.1", 1111);
787 const SocketAddress kRestartedCallerAddress("2.2.2.2", 2222);
788
789 auto caller = CreatePeerConnectionWithAudioVideo();
790 auto callee = CreatePeerConnectionWithAudioVideo();
791
Amit Hilbuchae3df542019-01-07 12:13:08 -0800792 auto offer = caller->CreateOfferAndSetAsLocal();
Steve Antonf1c6db12017-10-13 11:13:35 -0700793 cricket::Candidate old_candidate =
794 CreateLocalUdpCandidate(kFirstCallerAddress);
795 AddCandidateToFirstTransport(&old_candidate, offer.get());
796
797 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
798
799 RTCOfferAnswerOptions options;
800 options.ice_restart = true;
Amit Hilbuchae3df542019-01-07 12:13:08 -0800801 auto restart_offer = caller->CreateOfferAndSetAsLocal(options);
Steve Antonf1c6db12017-10-13 11:13:35 -0700802 cricket::Candidate new_candidate =
803 CreateLocalUdpCandidate(kRestartedCallerAddress);
804 AddCandidateToFirstTransport(&new_candidate, restart_offer.get());
805
806 ASSERT_TRUE(callee->SetRemoteDescription(std::move(restart_offer)));
807
808 auto remote_candidates = callee->GetIceCandidatesFromRemoteDescription();
809 ASSERT_EQ(1u, remote_candidates.size());
810 EXPECT_PRED_FORMAT2(AssertCandidatesEqual, new_candidate,
811 remote_candidates[0]->candidate());
812}
813
814// Test that if there is not an ICE restart (i.e., nothing changes), then the
815// answer to a later offer should have the same ufrag/pwd as the first answer.
Steve Anton46d926a2018-01-23 10:23:06 -0800816TEST_P(PeerConnectionIceTest, LaterAnswerHasSameIceCredentialsIfNoIceRestart) {
Steve Antonf1c6db12017-10-13 11:13:35 -0700817 auto caller = CreatePeerConnectionWithAudioVideo();
818 auto callee = CreatePeerConnectionWithAudioVideo();
819
820 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
821 ASSERT_TRUE(
822 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
823
824 // Re-offer.
825 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
826
827 auto answer = callee->CreateAnswer();
828 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
829 auto* local_transport_desc =
830 GetFirstTransportDescription(callee->pc()->local_description());
831
832 EXPECT_EQ(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
833 EXPECT_EQ(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
834}
835
Henrik Boström79b69802019-07-18 11:16:56 +0200836TEST_P(PeerConnectionIceTest, RestartIceGeneratesNewCredentials) {
837 auto caller = CreatePeerConnectionWithAudioVideo();
838 auto callee = CreatePeerConnectionWithAudioVideo();
839
840 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
841 auto initial_ice_credentials =
842 GetIceCredentials(caller->pc()->local_description());
843 caller->pc()->RestartIce();
844 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
845 auto restarted_ice_credentials =
846 GetIceCredentials(caller->pc()->local_description());
847 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
848}
849
850TEST_P(PeerConnectionIceTest,
851 RestartIceWhileLocalOfferIsPendingGeneratesNewCredentialsInNextOffer) {
852 auto caller = CreatePeerConnectionWithAudioVideo();
853 auto callee = CreatePeerConnectionWithAudioVideo();
854
855 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
856 auto initial_ice_credentials =
857 GetIceCredentials(caller->pc()->local_description());
858 // ICE restart becomes needed while an O/A is pending and |caller| is the
859 // offerer.
860 caller->pc()->RestartIce();
861 ASSERT_TRUE(
862 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
863 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
864 auto restarted_ice_credentials =
865 GetIceCredentials(caller->pc()->local_description());
866 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
867}
868
869TEST_P(PeerConnectionIceTest,
870 RestartIceWhileRemoteOfferIsPendingGeneratesNewCredentialsInNextOffer) {
871 auto caller = CreatePeerConnectionWithAudioVideo();
872 auto callee = CreatePeerConnectionWithAudioVideo();
873
874 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
875 auto initial_ice_credentials =
876 GetIceCredentials(caller->pc()->local_description());
877 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
878 // ICE restart becomes needed while an O/A is pending and |caller| is the
879 // answerer.
880 caller->pc()->RestartIce();
881 ASSERT_TRUE(
882 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
883 ASSERT_TRUE(caller->CreateOfferAndSetAsLocal());
884 auto restarted_ice_credentials =
885 GetIceCredentials(caller->pc()->local_description());
886 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
887}
888
889TEST_P(PeerConnectionIceTest, RestartIceTriggeredByRemoteSide) {
890 auto caller = CreatePeerConnectionWithAudioVideo();
891 auto callee = CreatePeerConnectionWithAudioVideo();
892
893 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
894 auto initial_ice_credentials =
895 GetIceCredentials(caller->pc()->local_description());
896
897 // Remote restart and O/A exchange with |caller| as the answerer should
898 // restart ICE locally as well.
899 callee->pc()->RestartIce();
900 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
901
902 auto restarted_ice_credentials =
903 GetIceCredentials(caller->pc()->local_description());
904 EXPECT_NE(initial_ice_credentials, restarted_ice_credentials);
905}
906
907TEST_P(PeerConnectionIceTest, RestartIceCausesNegotiationNeeded) {
908 auto caller = CreatePeerConnectionWithAudioVideo();
909 auto callee = CreatePeerConnectionWithAudioVideo();
910
911 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
912 caller->observer()->clear_negotiation_needed();
913 caller->pc()->RestartIce();
914 EXPECT_TRUE(caller->observer()->negotiation_needed());
915}
916
917// In Unified Plan, "onnegotiationneeded" is spec-compliant, including not
918// firing multipe times in a row, or firing when returning to the stable
919// signaling state if negotiation is still needed. In Plan B it fires any time
920// something changes. As such, some tests are SdpSemantics-specific.
921class PeerConnectionIceTestUnifiedPlan : public PeerConnectionIceBaseTest {
922 protected:
923 PeerConnectionIceTestUnifiedPlan()
924 : PeerConnectionIceBaseTest(SdpSemantics::kUnifiedPlan) {}
925};
926
927TEST_F(PeerConnectionIceTestUnifiedPlan,
928 RestartIceWhileLocalOfferIsPendingCausesNegotiationNeededWhenStable) {
929 auto caller = CreatePeerConnectionWithAudioVideo();
930 auto callee = CreatePeerConnectionWithAudioVideo();
931
932 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
933 // ICE restart becomes needed while an O/A is pending and |caller| is the
934 // offerer.
935 caller->observer()->clear_negotiation_needed();
936 caller->pc()->RestartIce();
937 // In Unified Plan, the event should not fire until we are back in the stable
938 // signaling state.
939 EXPECT_FALSE(caller->observer()->negotiation_needed());
940 ASSERT_TRUE(
941 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
942 EXPECT_TRUE(caller->observer()->negotiation_needed());
943}
944
945TEST_F(PeerConnectionIceTestUnifiedPlan,
946 RestartIceWhileRemoteOfferIsPendingCausesNegotiationNeededWhenStable) {
947 auto caller = CreatePeerConnectionWithAudioVideo();
948 auto callee = CreatePeerConnectionWithAudioVideo();
949
950 // Establish initial credentials as the caller.
951 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
952 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateOfferAndSetAsLocal()));
953 // ICE restart becomes needed while an O/A is pending and |caller| is the
954 // answerer.
955 caller->observer()->clear_negotiation_needed();
956 caller->pc()->RestartIce();
957 // In Unified Plan, the event should not fire until we are back in the stable
958 // signaling state.
959 EXPECT_FALSE(caller->observer()->negotiation_needed());
960 ASSERT_TRUE(
961 callee->SetRemoteDescription(caller->CreateAnswerAndSetAsLocal()));
962 EXPECT_TRUE(caller->observer()->negotiation_needed());
963}
964
965TEST_F(PeerConnectionIceTestUnifiedPlan,
966 RestartIceTriggeredByRemoteSideCauseNegotiationNotNeeded) {
967 auto caller = CreatePeerConnectionWithAudioVideo();
968 auto callee = CreatePeerConnectionWithAudioVideo();
969
970 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
971 // Local restart.
972 caller->pc()->RestartIce();
973 caller->observer()->clear_negotiation_needed();
974 // Remote restart and O/A exchange with |caller| as the answerer should
975 // restart ICE locally as well.
976 callee->pc()->RestartIce();
977 ASSERT_TRUE(callee->ExchangeOfferAnswerWith(caller.get()));
978 // Having restarted ICE by the remote offer, we do not need to renegotiate ICE
979 // credentials when back in the stable signaling state.
980 EXPECT_FALSE(caller->observer()->negotiation_needed());
981}
982
983TEST_F(PeerConnectionIceTestUnifiedPlan,
984 RestartIceTwiceDoesNotFireNegotiationNeededTwice) {
985 auto caller = CreatePeerConnectionWithAudioVideo();
986 auto callee = CreatePeerConnectionWithAudioVideo();
987
988 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
989 caller->pc()->RestartIce();
990 EXPECT_TRUE(caller->observer()->negotiation_needed());
991 caller->observer()->clear_negotiation_needed();
992 caller->pc()->RestartIce();
993 EXPECT_FALSE(caller->observer()->negotiation_needed());
994}
995
996// In Plan B, "onnegotiationneeded" is not spec-compliant, firing based on if
997// something changed rather than if negotiation is needed. In Unified Plan it
998// fires according to spec. As such, some tests are SdpSemantics-specific.
999class PeerConnectionIceTestPlanB : public PeerConnectionIceBaseTest {
1000 protected:
1001 PeerConnectionIceTestPlanB()
1002 : PeerConnectionIceBaseTest(SdpSemantics::kPlanB) {}
1003};
1004
1005TEST_F(PeerConnectionIceTestPlanB,
1006 RestartIceWhileOfferIsPendingCausesNegotiationNeededImmediately) {
1007 auto caller = CreatePeerConnectionWithAudioVideo();
1008 auto callee = CreatePeerConnectionWithAudioVideo();
1009
1010 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1011 caller->observer()->clear_negotiation_needed();
1012 caller->pc()->RestartIce();
1013 EXPECT_TRUE(caller->observer()->negotiation_needed());
1014 caller->observer()->clear_negotiation_needed();
1015 ASSERT_TRUE(
1016 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1017 // In Plan B, the event fired early so we don't expect it to fire now. This is
1018 // not spec-compliant but follows the pattern of existing Plan B behavior.
1019 EXPECT_FALSE(caller->observer()->negotiation_needed());
1020}
1021
1022TEST_F(PeerConnectionIceTestPlanB,
1023 RestartIceTwiceDoesFireNegotiationNeededTwice) {
1024 auto caller = CreatePeerConnectionWithAudioVideo();
1025 auto callee = CreatePeerConnectionWithAudioVideo();
1026
1027 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
1028 caller->observer()->clear_negotiation_needed();
1029 caller->pc()->RestartIce();
1030 EXPECT_TRUE(caller->observer()->negotiation_needed());
1031 caller->observer()->clear_negotiation_needed();
1032 caller->pc()->RestartIce();
1033 // In Plan B, the event fires every time something changed, even if we have
1034 // already fired the event. This is not spec-compliant but follows the same
1035 // pattern of existing Plan B behavior.
1036 EXPECT_TRUE(caller->observer()->negotiation_needed());
1037}
1038
Steve Antonf1c6db12017-10-13 11:13:35 -07001039// The following parameterized test verifies that if an offer is sent with a
1040// modified ICE ufrag and/or ICE pwd, then the answer should identify that the
1041// other side has initiated an ICE restart and generate a new ufrag and pwd.
1042// RFC 5245 says: "If the offer contained a change in the a=ice-ufrag or
1043// a=ice-pwd attributes compared to the previous SDP from the peer, it
1044// indicates that ICE is restarting for this media stream."
1045
Steve Anton46d926a2018-01-23 10:23:06 -08001046class PeerConnectionIceUfragPwdAnswerTest
1047 : public PeerConnectionIceBaseTest,
1048 public ::testing::WithParamInterface<
1049 std::tuple<SdpSemantics, std::tuple<bool, bool>>> {
Steve Antonf1c6db12017-10-13 11:13:35 -07001050 protected:
Steve Anton46d926a2018-01-23 10:23:06 -08001051 PeerConnectionIceUfragPwdAnswerTest()
1052 : PeerConnectionIceBaseTest(std::get<0>(GetParam())) {
1053 auto param = std::get<1>(GetParam());
1054 offer_new_ufrag_ = std::get<0>(param);
1055 offer_new_pwd_ = std::get<1>(param);
Steve Antonf1c6db12017-10-13 11:13:35 -07001056 }
1057
1058 bool offer_new_ufrag_;
1059 bool offer_new_pwd_;
1060};
1061
Steve Anton46d926a2018-01-23 10:23:06 -08001062TEST_P(PeerConnectionIceUfragPwdAnswerTest, TestIncludedInAnswer) {
Steve Antonf1c6db12017-10-13 11:13:35 -07001063 auto caller = CreatePeerConnectionWithAudioVideo();
1064 auto callee = CreatePeerConnectionWithAudioVideo();
1065
1066 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1067 ASSERT_TRUE(
1068 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1069
1070 auto offer = caller->CreateOffer();
1071 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1072 if (offer_new_ufrag_) {
1073 offer_transport_desc->ice_ufrag += "_new";
1074 }
1075 if (offer_new_pwd_) {
1076 offer_transport_desc->ice_pwd += "_new";
1077 }
1078
1079 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1080
1081 auto answer = callee->CreateAnswer();
1082 auto* answer_transport_desc = GetFirstTransportDescription(answer.get());
1083 auto* local_transport_desc =
1084 GetFirstTransportDescription(callee->pc()->local_description());
1085
1086 EXPECT_NE(answer_transport_desc->ice_ufrag, local_transport_desc->ice_ufrag);
1087 EXPECT_NE(answer_transport_desc->ice_pwd, local_transport_desc->ice_pwd);
1088}
1089
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001090INSTANTIATE_TEST_SUITE_P(
Steve Anton46d926a2018-01-23 10:23:06 -08001091 PeerConnectionIceTest,
1092 PeerConnectionIceUfragPwdAnswerTest,
1093 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
1094 Values(std::make_pair(true, true), // Both changed.
1095 std::make_pair(true, false), // Only ufrag changed.
1096 std::make_pair(false, true)))); // Only pwd changed.
Steve Antonf1c6db12017-10-13 11:13:35 -07001097
1098// Test that if an ICE restart is offered on one media section, then the answer
1099// will only change ICE ufrag/pwd for that section and keep the other sections
1100// the same.
1101// Note that this only works if we have disabled BUNDLE, otherwise all media
1102// sections will share the same transport.
Steve Anton46d926a2018-01-23 10:23:06 -08001103TEST_P(PeerConnectionIceTest,
Steve Antonf1c6db12017-10-13 11:13:35 -07001104 CreateAnswerHasNewUfragPwdForOnlyMediaSectionWhichRestarted) {
1105 auto caller = CreatePeerConnectionWithAudioVideo();
1106 auto callee = CreatePeerConnectionWithAudioVideo();
1107
1108 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1109 ASSERT_TRUE(
1110 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1111
1112 RTCOfferAnswerOptions disable_bundle_options;
1113 disable_bundle_options.use_rtp_mux = false;
1114
1115 auto offer = caller->CreateOffer(disable_bundle_options);
1116
1117 // Signal ICE restart on the first media section.
1118 auto* offer_transport_desc = GetFirstTransportDescription(offer.get());
1119 offer_transport_desc->ice_ufrag += "_new";
1120 offer_transport_desc->ice_pwd += "_new";
1121
1122 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1123
1124 auto answer = callee->CreateAnswer(disable_bundle_options);
1125 const auto& answer_transports = answer->description()->transport_infos();
1126 const auto& local_transports =
1127 callee->pc()->local_description()->description()->transport_infos();
1128
1129 EXPECT_NE(answer_transports[0].description.ice_ufrag,
1130 local_transports[0].description.ice_ufrag);
1131 EXPECT_NE(answer_transports[0].description.ice_pwd,
1132 local_transports[0].description.ice_pwd);
1133 EXPECT_EQ(answer_transports[1].description.ice_ufrag,
1134 local_transports[1].description.ice_ufrag);
1135 EXPECT_EQ(answer_transports[1].description.ice_pwd,
1136 local_transports[1].description.ice_pwd);
1137}
1138
Qingsi Wange1692722017-11-29 13:27:20 -08001139// Test that when the initial offerer (caller) uses the lite implementation of
1140// ICE and the callee uses the full implementation, the caller takes the
1141// CONTROLLED role and the callee takes the CONTROLLING role. This is specified
1142// in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -08001143TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -08001144 OfferFromLiteIceControlledAndAnswerFromFullIceControlling) {
1145 auto caller = CreatePeerConnectionWithAudioVideo();
1146 auto callee = CreatePeerConnectionWithAudioVideo();
1147
1148 auto offer = caller->CreateOffer();
1149 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1150 ASSERT_TRUE(
1151 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1152 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1153
1154 auto answer = callee->CreateAnswer();
1155 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_FULL);
1156 ASSERT_TRUE(
1157 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1158 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1159
1160 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(caller));
1161 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(callee));
1162}
1163
1164// Test that when the caller and the callee both use the lite implementation of
1165// ICE, the initial offerer (caller) takes the CONTROLLING role and the callee
1166// takes the CONTROLLED role. This is specified in RFC5245 Section 5.1.1.
Steve Anton46d926a2018-01-23 10:23:06 -08001167TEST_P(PeerConnectionIceTest,
Qingsi Wange1692722017-11-29 13:27:20 -08001168 OfferFromLiteIceControllingAndAnswerFromLiteIceControlled) {
1169 auto caller = CreatePeerConnectionWithAudioVideo();
1170 auto callee = CreatePeerConnectionWithAudioVideo();
1171
1172 auto offer = caller->CreateOffer();
1173 SetIceMode(offer.get(), cricket::IceMode::ICEMODE_LITE);
1174 ASSERT_TRUE(
1175 caller->SetLocalDescription(CloneSessionDescription(offer.get())));
1176 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1177
1178 auto answer = callee->CreateAnswer();
1179 SetIceMode(answer.get(), cricket::IceMode::ICEMODE_LITE);
1180 ASSERT_TRUE(
1181 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1182 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
1183
1184 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, GetIceRole(caller));
1185 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, GetIceRole(callee));
1186}
1187
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001188INSTANTIATE_TEST_SUITE_P(PeerConnectionIceTest,
1189 PeerConnectionIceTest,
1190 Values(SdpSemantics::kPlanB,
1191 SdpSemantics::kUnifiedPlan));
Steve Anton46d926a2018-01-23 10:23:06 -08001192
Mirko Bonadei6a489f22019-04-09 15:11:12 +02001193class PeerConnectionIceConfigTest : public ::testing::Test {
Qingsi Wang4ff54432018-03-01 18:25:20 -08001194 protected:
1195 void SetUp() override {
1196 pc_factory_ = CreatePeerConnectionFactory(
1197 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
1198 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
Anders Carlsson67537952018-05-03 11:28:29 +02001199 CreateBuiltinAudioDecoderFactory(), CreateBuiltinVideoEncoderFactory(),
1200 CreateBuiltinVideoDecoderFactory(), nullptr /* audio_mixer */,
1201 nullptr /* audio_processing */);
Qingsi Wang4ff54432018-03-01 18:25:20 -08001202 }
1203 void CreatePeerConnection(const RTCConfiguration& config) {
1204 std::unique_ptr<cricket::FakePortAllocator> port_allocator(
1205 new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr));
1206 port_allocator_ = port_allocator.get();
1207 rtc::scoped_refptr<PeerConnectionInterface> pc(
Niels Möllerf06f9232018-08-07 12:32:18 +02001208 pc_factory_->CreatePeerConnection(config, std::move(port_allocator),
1209 nullptr /* cert_generator */,
1210 &observer_));
Qingsi Wang4ff54432018-03-01 18:25:20 -08001211 EXPECT_TRUE(pc.get());
Mirko Bonadei1c546052019-02-04 14:50:38 +01001212 pc_ = std::move(pc);
Qingsi Wang4ff54432018-03-01 18:25:20 -08001213 }
1214
1215 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_ = nullptr;
1216 rtc::scoped_refptr<PeerConnectionInterface> pc_ = nullptr;
1217 cricket::FakePortAllocator* port_allocator_ = nullptr;
1218
1219 MockPeerConnectionObserver observer_;
1220};
1221
1222TEST_F(PeerConnectionIceConfigTest, SetStunCandidateKeepaliveInterval) {
1223 RTCConfiguration config;
1224 config.stun_candidate_keepalive_interval = 123;
1225 config.ice_candidate_pool_size = 1;
1226 CreatePeerConnection(config);
1227 ASSERT_NE(port_allocator_, nullptr);
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001228 absl::optional<int> actual_stun_keepalive_interval =
Qingsi Wang4ff54432018-03-01 18:25:20 -08001229 port_allocator_->stun_candidate_keepalive_interval();
1230 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 123);
1231 config.stun_candidate_keepalive_interval = 321;
Niels Möller2579f0c2019-08-19 09:58:17 +02001232 ASSERT_TRUE(pc_->SetConfiguration(config).ok());
Qingsi Wang4ff54432018-03-01 18:25:20 -08001233 actual_stun_keepalive_interval =
1234 port_allocator_->stun_candidate_keepalive_interval();
1235 EXPECT_EQ(actual_stun_keepalive_interval.value_or(-1), 321);
1236}
1237
Jonas Oreland1cd39fa2018-10-11 07:47:12 +02001238TEST_P(PeerConnectionIceTest, IceCredentialsCreateOffer) {
1239 RTCConfiguration config;
1240 config.ice_candidate_pool_size = 1;
1241 auto pc = CreatePeerConnectionWithAudioVideo(config);
1242 ASSERT_NE(pc->port_allocator_, nullptr);
1243 auto offer = pc->CreateOffer();
1244 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1245 ASSERT_EQ(1u, credentials.size());
1246
1247 auto* desc = offer->description();
1248 for (const auto& content : desc->contents()) {
1249 auto* transport_info = desc->GetTransportInfoByName(content.name);
1250 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1251 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1252 }
1253}
1254
1255TEST_P(PeerConnectionIceTest, IceCredentialsCreateAnswer) {
1256 RTCConfiguration config;
1257 config.ice_candidate_pool_size = 1;
1258 auto pc = CreatePeerConnectionWithAudioVideo(config);
1259 ASSERT_NE(pc->port_allocator_, nullptr);
1260 auto offer = pc->CreateOffer();
1261 ASSERT_TRUE(pc->SetRemoteDescription(std::move(offer)));
1262 auto answer = pc->CreateAnswer();
1263
1264 auto credentials = pc->port_allocator_->GetPooledIceCredentials();
1265 ASSERT_EQ(1u, credentials.size());
1266
1267 auto* desc = answer->description();
1268 for (const auto& content : desc->contents()) {
1269 auto* transport_info = desc->GetTransportInfoByName(content.name);
1270 EXPECT_EQ(transport_info->description.ice_ufrag, credentials[0].ufrag);
1271 EXPECT_EQ(transport_info->description.ice_pwd, credentials[0].pwd);
1272 }
1273}
1274
Steve Antonf1c6db12017-10-13 11:13:35 -07001275} // namespace webrtc