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