1 /*
2 * Copyright 2022 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
11 // This file is intended for PeerConnection integration tests that are
12 // slow to execute (currently defined as more than 5 seconds per test).
13
14 #include <stdint.h>
15
16 #include <memory>
17 #include <string>
18 #include <tuple>
19 #include <utility>
20 #include <vector>
21
22 #include "absl/algorithm/container.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/types/optional.h"
25 #include "api/dtmf_sender_interface.h"
26 #include "api/peer_connection_interface.h"
27 #include "api/rtp_receiver_interface.h"
28 #include "api/scoped_refptr.h"
29 #include "api/units/time_delta.h"
30 #include "p2p/base/port_allocator.h"
31 #include "p2p/base/port_interface.h"
32 #include "p2p/base/stun_server.h"
33 #include "p2p/base/test_stun_server.h"
34 #include "pc/test/integration_test_helpers.h"
35 #include "pc/test/mock_peer_connection_observers.h"
36 #include "rtc_base/fake_clock.h"
37 #include "rtc_base/fake_network.h"
38 #include "rtc_base/firewall_socket_server.h"
39 #include "rtc_base/gunit.h"
40 #include "rtc_base/logging.h"
41 #include "rtc_base/socket_address.h"
42 #include "rtc_base/ssl_certificate.h"
43 #include "rtc_base/test_certificate_verifier.h"
44 #include "test/gmock.h"
45 #include "test/gtest.h"
46
47 namespace webrtc {
48
49 namespace {
50
51 class PeerConnectionIntegrationTest
52 : public PeerConnectionIntegrationBaseTest,
53 public ::testing::WithParamInterface<
54 std::tuple<SdpSemantics, std::string>> {
55 protected:
PeerConnectionIntegrationTest()56 PeerConnectionIntegrationTest()
57 : PeerConnectionIntegrationBaseTest(std::get<0>(GetParam()),
58 std::get<1>(GetParam())) {}
59 };
60
61 // Fake clock must be set before threads are started to prevent race on
62 // Set/GetClockForTesting().
63 // To achieve that, multiple inheritance is used as a mixin pattern
64 // where order of construction is finely controlled.
65 // This also ensures peerconnection is closed before switching back to non-fake
66 // clock, avoiding other races and DCHECK failures such as in rtp_sender.cc.
67 class FakeClockForTest : public rtc::ScopedFakeClock {
68 protected:
FakeClockForTest()69 FakeClockForTest() {
70 // Some things use a time of "0" as a special value, so we need to start out
71 // the fake clock at a nonzero time.
72 // TODO(deadbeef): Fix this.
73 AdvanceTime(webrtc::TimeDelta::Seconds(1));
74 }
75
76 // Explicit handle.
FakeClock()77 ScopedFakeClock& FakeClock() { return *this; }
78 };
79
80 // Ensure FakeClockForTest is constructed first (see class for rationale).
81 class PeerConnectionIntegrationTestWithFakeClock
82 : public FakeClockForTest,
83 public PeerConnectionIntegrationTest {};
84
85 class PeerConnectionIntegrationTestPlanB
86 : public PeerConnectionIntegrationBaseTest {
87 protected:
PeerConnectionIntegrationTestPlanB()88 PeerConnectionIntegrationTestPlanB()
89 : PeerConnectionIntegrationBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
90 };
91
92 class PeerConnectionIntegrationTestUnifiedPlan
93 : public PeerConnectionIntegrationBaseTest {
94 protected:
PeerConnectionIntegrationTestUnifiedPlan()95 PeerConnectionIntegrationTestUnifiedPlan()
96 : PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {}
97 };
98
99 // Test the OnFirstPacketReceived callback from audio/video RtpReceivers. This
100 // includes testing that the callback is invoked if an observer is connected
101 // after the first packet has already been received.
TEST_P(PeerConnectionIntegrationTest,RtpReceiverObserverOnFirstPacketReceived)102 TEST_P(PeerConnectionIntegrationTest,
103 RtpReceiverObserverOnFirstPacketReceived) {
104 ASSERT_TRUE(CreatePeerConnectionWrappers());
105 ConnectFakeSignaling();
106 caller()->AddAudioVideoTracks();
107 callee()->AddAudioVideoTracks();
108 // Start offer/answer exchange and wait for it to complete.
109 caller()->CreateAndSetAndSignalOffer();
110 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
111 // Should be one receiver each for audio/video.
112 EXPECT_EQ(2U, caller()->rtp_receiver_observers().size());
113 EXPECT_EQ(2U, callee()->rtp_receiver_observers().size());
114 // Wait for all "first packet received" callbacks to be fired.
115 EXPECT_TRUE_WAIT(
116 absl::c_all_of(caller()->rtp_receiver_observers(),
117 [](const std::unique_ptr<MockRtpReceiverObserver>& o) {
118 return o->first_packet_received();
119 }),
120 kMaxWaitForFramesMs);
121 EXPECT_TRUE_WAIT(
122 absl::c_all_of(callee()->rtp_receiver_observers(),
123 [](const std::unique_ptr<MockRtpReceiverObserver>& o) {
124 return o->first_packet_received();
125 }),
126 kMaxWaitForFramesMs);
127 // If new observers are set after the first packet was already received, the
128 // callback should still be invoked.
129 caller()->ResetRtpReceiverObservers();
130 callee()->ResetRtpReceiverObservers();
131 EXPECT_EQ(2U, caller()->rtp_receiver_observers().size());
132 EXPECT_EQ(2U, callee()->rtp_receiver_observers().size());
133 EXPECT_TRUE(
134 absl::c_all_of(caller()->rtp_receiver_observers(),
135 [](const std::unique_ptr<MockRtpReceiverObserver>& o) {
136 return o->first_packet_received();
137 }));
138 EXPECT_TRUE(
139 absl::c_all_of(callee()->rtp_receiver_observers(),
140 [](const std::unique_ptr<MockRtpReceiverObserver>& o) {
141 return o->first_packet_received();
142 }));
143 }
144
145 class DummyDtmfObserver : public DtmfSenderObserverInterface {
146 public:
DummyDtmfObserver()147 DummyDtmfObserver() : completed_(false) {}
148
149 // Implements DtmfSenderObserverInterface.
OnToneChange(const std::string & tone)150 void OnToneChange(const std::string& tone) override {
151 tones_.push_back(tone);
152 if (tone.empty()) {
153 completed_ = true;
154 }
155 }
156
tones() const157 const std::vector<std::string>& tones() const { return tones_; }
completed() const158 bool completed() const { return completed_; }
159
160 private:
161 bool completed_;
162 std::vector<std::string> tones_;
163 };
164
TEST_P(PeerConnectionIntegrationTest,SSLCertificateVerifierFailureUsedForTurnConnectionsFailsConnection)165 TEST_P(PeerConnectionIntegrationTest,
166 SSLCertificateVerifierFailureUsedForTurnConnectionsFailsConnection) {
167 static const rtc::SocketAddress turn_server_internal_address{"88.88.88.0",
168 3478};
169 static const rtc::SocketAddress turn_server_external_address{"88.88.88.1", 0};
170
171 // Enable TCP-TLS for the fake turn server. We need to pass in 88.88.88.0 so
172 // that host name verification passes on the fake certificate.
173 CreateTurnServer(turn_server_internal_address, turn_server_external_address,
174 cricket::PROTO_TLS, "88.88.88.0");
175
176 webrtc::PeerConnectionInterface::IceServer ice_server;
177 ice_server.urls.push_back("turns:88.88.88.0:3478?transport=tcp");
178 ice_server.username = "test";
179 ice_server.password = "test";
180
181 PeerConnectionInterface::RTCConfiguration client_1_config;
182 client_1_config.servers.push_back(ice_server);
183 client_1_config.type = webrtc::PeerConnectionInterface::kRelay;
184
185 PeerConnectionInterface::RTCConfiguration client_2_config;
186 client_2_config.servers.push_back(ice_server);
187 // Setting the type to kRelay forces the connection to go through a TURN
188 // server.
189 client_2_config.type = webrtc::PeerConnectionInterface::kRelay;
190
191 // Get a copy to the pointer so we can verify calls later.
192 rtc::TestCertificateVerifier* client_1_cert_verifier =
193 new rtc::TestCertificateVerifier();
194 client_1_cert_verifier->verify_certificate_ = false;
195 rtc::TestCertificateVerifier* client_2_cert_verifier =
196 new rtc::TestCertificateVerifier();
197 client_2_cert_verifier->verify_certificate_ = false;
198
199 // Create the dependencies with the test certificate verifier.
200 webrtc::PeerConnectionDependencies client_1_deps(nullptr);
201 client_1_deps.tls_cert_verifier =
202 std::unique_ptr<rtc::TestCertificateVerifier>(client_1_cert_verifier);
203 webrtc::PeerConnectionDependencies client_2_deps(nullptr);
204 client_2_deps.tls_cert_verifier =
205 std::unique_ptr<rtc::TestCertificateVerifier>(client_2_cert_verifier);
206
207 ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndDeps(
208 client_1_config, std::move(client_1_deps), client_2_config,
209 std::move(client_2_deps)));
210 ConnectFakeSignaling();
211
212 // Set "offer to receive audio/video" without adding any tracks, so we just
213 // set up ICE/DTLS with no media.
214 PeerConnectionInterface::RTCOfferAnswerOptions options;
215 options.offer_to_receive_audio = 1;
216 options.offer_to_receive_video = 1;
217 caller()->SetOfferAnswerOptions(options);
218 caller()->CreateAndSetAndSignalOffer();
219 bool wait_res = true;
220 // TODO(bugs.webrtc.org/9219): When IceConnectionState is implemented
221 // properly, should be able to just wait for a state of "failed" instead of
222 // waiting a fixed 10 seconds.
223 WAIT_(DtlsConnected(), kDefaultTimeout, wait_res);
224 ASSERT_FALSE(wait_res);
225
226 EXPECT_GT(client_1_cert_verifier->call_count_, 0u);
227 EXPECT_GT(client_2_cert_verifier->call_count_, 0u);
228 }
229
230 // Test that we can get capture start ntp time.
TEST_P(PeerConnectionIntegrationTest,GetCaptureStartNtpTimeWithOldStatsApi)231 TEST_P(PeerConnectionIntegrationTest, GetCaptureStartNtpTimeWithOldStatsApi) {
232 ASSERT_TRUE(CreatePeerConnectionWrappers());
233 ConnectFakeSignaling();
234 caller()->AddAudioTrack();
235
236 callee()->AddAudioTrack();
237
238 // Do offer/answer, wait for the callee to receive some frames.
239 caller()->CreateAndSetAndSignalOffer();
240 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
241
242 // Get the remote audio track created on the receiver, so they can be used as
243 // GetStats filters.
244 auto receivers = callee()->pc()->GetReceivers();
245 ASSERT_EQ(1u, receivers.size());
246 auto remote_audio_track = receivers[0]->track();
247
248 // Get the audio output level stats. Note that the level is not available
249 // until an RTCP packet has been received.
250 EXPECT_TRUE_WAIT(callee()->OldGetStatsForTrack(remote_audio_track.get())
251 ->CaptureStartNtpTime() > 0,
252 2 * kMaxWaitForFramesMs);
253 }
254
255 // Test that firewalling the ICE connection causes the clients to identify the
256 // disconnected state and then removing the firewall causes them to reconnect.
257 class PeerConnectionIntegrationIceStatesTest
258 : public PeerConnectionIntegrationBaseTest,
259 public ::testing::WithParamInterface<
260 std::tuple<SdpSemantics, std::tuple<std::string, uint32_t>>> {
261 protected:
PeerConnectionIntegrationIceStatesTest()262 PeerConnectionIntegrationIceStatesTest()
263 : PeerConnectionIntegrationBaseTest(std::get<0>(GetParam())) {
264 port_allocator_flags_ = std::get<1>(std::get<1>(GetParam()));
265 }
266
StartStunServer(const SocketAddress & server_address)267 void StartStunServer(const SocketAddress& server_address) {
268 stun_server_.reset(
269 cricket::TestStunServer::Create(firewall(), server_address));
270 }
271
TestIPv6()272 bool TestIPv6() {
273 return (port_allocator_flags_ & cricket::PORTALLOCATOR_ENABLE_IPV6);
274 }
275
SetPortAllocatorFlags()276 void SetPortAllocatorFlags() {
277 PeerConnectionIntegrationBaseTest::SetPortAllocatorFlags(
278 port_allocator_flags_, port_allocator_flags_);
279 }
280
CallerAddresses()281 std::vector<SocketAddress> CallerAddresses() {
282 std::vector<SocketAddress> addresses;
283 addresses.push_back(SocketAddress("1.1.1.1", 0));
284 if (TestIPv6()) {
285 addresses.push_back(SocketAddress("1111:0:a:b:c:d:e:f", 0));
286 }
287 return addresses;
288 }
289
CalleeAddresses()290 std::vector<SocketAddress> CalleeAddresses() {
291 std::vector<SocketAddress> addresses;
292 addresses.push_back(SocketAddress("2.2.2.2", 0));
293 if (TestIPv6()) {
294 addresses.push_back(SocketAddress("2222:0:a:b:c:d:e:f", 0));
295 }
296 return addresses;
297 }
298
SetUpNetworkInterfaces()299 void SetUpNetworkInterfaces() {
300 // Remove the default interfaces added by the test infrastructure.
301 caller()->network_manager()->RemoveInterface(kDefaultLocalAddress);
302 callee()->network_manager()->RemoveInterface(kDefaultLocalAddress);
303
304 // Add network addresses for test.
305 for (const auto& caller_address : CallerAddresses()) {
306 caller()->network_manager()->AddInterface(caller_address);
307 }
308 for (const auto& callee_address : CalleeAddresses()) {
309 callee()->network_manager()->AddInterface(callee_address);
310 }
311 }
312
313 private:
314 uint32_t port_allocator_flags_;
315 std::unique_ptr<cricket::TestStunServer> stun_server_;
316 };
317
318 // Ensure FakeClockForTest is constructed first (see class for rationale).
319 class PeerConnectionIntegrationIceStatesTestWithFakeClock
320 : public FakeClockForTest,
321 public PeerConnectionIntegrationIceStatesTest {};
322
323 #if !defined(THREAD_SANITIZER)
324 // This test provokes TSAN errors. bugs.webrtc.org/11282
325
326 // Tests that the PeerConnection goes through all the ICE gathering/connection
327 // states over the duration of the call. This includes Disconnected and Failed
328 // states, induced by putting a firewall between the peers and waiting for them
329 // to time out.
TEST_P(PeerConnectionIntegrationIceStatesTestWithFakeClock,VerifyIceStates)330 TEST_P(PeerConnectionIntegrationIceStatesTestWithFakeClock, VerifyIceStates) {
331 const SocketAddress kStunServerAddress =
332 SocketAddress("99.99.99.1", cricket::STUN_SERVER_PORT);
333 StartStunServer(kStunServerAddress);
334
335 PeerConnectionInterface::RTCConfiguration config;
336 PeerConnectionInterface::IceServer ice_stun_server;
337 ice_stun_server.urls.push_back(
338 "stun:" + kStunServerAddress.HostAsURIString() + ":" +
339 kStunServerAddress.PortAsString());
340 config.servers.push_back(ice_stun_server);
341
342 ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(config, config));
343 ConnectFakeSignaling();
344 SetPortAllocatorFlags();
345 SetUpNetworkInterfaces();
346 caller()->AddAudioVideoTracks();
347 callee()->AddAudioVideoTracks();
348
349 // Initial state before anything happens.
350 ASSERT_EQ(PeerConnectionInterface::kIceGatheringNew,
351 caller()->ice_gathering_state());
352 ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew,
353 caller()->ice_connection_state());
354 ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew,
355 caller()->standardized_ice_connection_state());
356
357 // Start the call by creating the offer, setting it as the local description,
358 // then sending it to the peer who will respond with an answer. This happens
359 // asynchronously so that we can watch the states as it runs in the
360 // background.
361 caller()->CreateAndSetAndSignalOffer();
362
363 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
364 caller()->ice_connection_state(), kDefaultTimeout,
365 FakeClock());
366 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
367 caller()->standardized_ice_connection_state(),
368 kDefaultTimeout, FakeClock());
369
370 // Verify that the observer was notified of the intermediate transitions.
371 EXPECT_THAT(caller()->ice_connection_state_history(),
372 ElementsAre(PeerConnectionInterface::kIceConnectionChecking,
373 PeerConnectionInterface::kIceConnectionConnected,
374 PeerConnectionInterface::kIceConnectionCompleted));
375 EXPECT_THAT(caller()->standardized_ice_connection_state_history(),
376 ElementsAre(PeerConnectionInterface::kIceConnectionChecking,
377 PeerConnectionInterface::kIceConnectionConnected,
378 PeerConnectionInterface::kIceConnectionCompleted));
379 EXPECT_THAT(
380 caller()->peer_connection_state_history(),
381 ElementsAre(PeerConnectionInterface::PeerConnectionState::kConnecting,
382 PeerConnectionInterface::PeerConnectionState::kConnected));
383 EXPECT_THAT(caller()->ice_gathering_state_history(),
384 ElementsAre(PeerConnectionInterface::kIceGatheringGathering,
385 PeerConnectionInterface::kIceGatheringComplete));
386
387 // Block connections to/from the caller and wait for ICE to become
388 // disconnected.
389 for (const auto& caller_address : CallerAddresses()) {
390 firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address);
391 }
392 RTC_LOG(LS_INFO) << "Firewall rules applied";
393 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
394 caller()->ice_connection_state(), kDefaultTimeout,
395 FakeClock());
396 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
397 caller()->standardized_ice_connection_state(),
398 kDefaultTimeout, FakeClock());
399
400 // Let ICE re-establish by removing the firewall rules.
401 firewall()->ClearRules();
402 RTC_LOG(LS_INFO) << "Firewall rules cleared";
403 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
404 caller()->ice_connection_state(), kDefaultTimeout,
405 FakeClock());
406 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
407 caller()->standardized_ice_connection_state(),
408 kDefaultTimeout, FakeClock());
409
410 // According to RFC7675, if there is no response within 30 seconds then the
411 // peer should consider the other side to have rejected the connection. This
412 // is signaled by the state transitioning to "failed".
413 constexpr int kConsentTimeout = 30000;
414 for (const auto& caller_address : CallerAddresses()) {
415 firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address);
416 }
417 RTC_LOG(LS_INFO) << "Firewall rules applied again";
418 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed,
419 caller()->ice_connection_state(), kConsentTimeout,
420 FakeClock());
421 ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed,
422 caller()->standardized_ice_connection_state(),
423 kConsentTimeout, FakeClock());
424 }
425 #endif
426
427 // This test sets up a call that's transferred to a new caller with a different
428 // DTLS fingerprint.
TEST_P(PeerConnectionIntegrationTest,CallTransferredForCallee)429 TEST_P(PeerConnectionIntegrationTest, CallTransferredForCallee) {
430 ASSERT_TRUE(CreatePeerConnectionWrappers());
431 ConnectFakeSignaling();
432 caller()->AddAudioVideoTracks();
433 callee()->AddAudioVideoTracks();
434 caller()->CreateAndSetAndSignalOffer();
435 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
436
437 // Keep the original peer around which will still send packets to the
438 // receiving client. These SRTP packets will be dropped.
439 std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer(
440 SetCallerPcWrapperAndReturnCurrent(
441 CreatePeerConnectionWrapperWithAlternateKey().release()));
442 // TODO(deadbeef): Why do we call Close here? That goes against the comment
443 // directly above.
444 original_peer->pc()->Close();
445
446 ConnectFakeSignaling();
447 caller()->AddAudioVideoTracks();
448 caller()->CreateAndSetAndSignalOffer();
449 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
450 // Wait for some additional frames to be transmitted end-to-end.
451 MediaExpectations media_expectations;
452 media_expectations.ExpectBidirectionalAudioAndVideo();
453 ASSERT_TRUE(ExpectNewFrames(media_expectations));
454 }
455
456 // This test sets up a call that's transferred to a new callee with a different
457 // DTLS fingerprint.
TEST_P(PeerConnectionIntegrationTest,CallTransferredForCaller)458 TEST_P(PeerConnectionIntegrationTest, CallTransferredForCaller) {
459 ASSERT_TRUE(CreatePeerConnectionWrappers());
460 ConnectFakeSignaling();
461 caller()->AddAudioVideoTracks();
462 callee()->AddAudioVideoTracks();
463 caller()->CreateAndSetAndSignalOffer();
464 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
465
466 // Keep the original peer around which will still send packets to the
467 // receiving client. These SRTP packets will be dropped.
468 std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer(
469 SetCalleePcWrapperAndReturnCurrent(
470 CreatePeerConnectionWrapperWithAlternateKey().release()));
471 // TODO(deadbeef): Why do we call Close here? That goes against the comment
472 // directly above.
473 original_peer->pc()->Close();
474
475 ConnectFakeSignaling();
476 callee()->AddAudioVideoTracks();
477 caller()->SetOfferAnswerOptions(IceRestartOfferAnswerOptions());
478 caller()->CreateAndSetAndSignalOffer();
479 ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
480 // Wait for some additional frames to be transmitted end-to-end.
481 MediaExpectations media_expectations;
482 media_expectations.ExpectBidirectionalAudioAndVideo();
483 ASSERT_TRUE(ExpectNewFrames(media_expectations));
484 }
485
486 INSTANTIATE_TEST_SUITE_P(
487 PeerConnectionIntegrationTest,
488 PeerConnectionIntegrationTest,
489 Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
490 Values("WebRTC-FrameBuffer3/arm:FrameBuffer2/",
491 "WebRTC-FrameBuffer3/arm:FrameBuffer3/",
492 "WebRTC-FrameBuffer3/arm:SyncDecoding/")));
493
494 constexpr uint32_t kFlagsIPv4NoStun = cricket::PORTALLOCATOR_DISABLE_TCP |
495 cricket::PORTALLOCATOR_DISABLE_STUN |
496 cricket::PORTALLOCATOR_DISABLE_RELAY;
497 constexpr uint32_t kFlagsIPv6NoStun =
498 cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_STUN |
499 cricket::PORTALLOCATOR_ENABLE_IPV6 | cricket::PORTALLOCATOR_DISABLE_RELAY;
500 constexpr uint32_t kFlagsIPv4Stun =
501 cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_RELAY;
502
503 INSTANTIATE_TEST_SUITE_P(
504 PeerConnectionIntegrationTest,
505 PeerConnectionIntegrationIceStatesTestWithFakeClock,
506 Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan),
507 Values(std::make_pair("IPv4 no STUN", kFlagsIPv4NoStun),
508 std::make_pair("IPv6 no STUN", kFlagsIPv6NoStun),
509 std::make_pair("IPv4 with STUN", kFlagsIPv4Stun))));
510
511 } // namespace
512 } // namespace webrtc
513