xref: /aosp_15_r20/external/webrtc/pc/peer_connection_histogram_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
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 
11 #include <memory>
12 #include <set>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "absl/types/optional.h"
18 #include "api/async_resolver_factory.h"
19 #include "api/call/call_factory_interface.h"
20 #include "api/jsep.h"
21 #include "api/jsep_session_description.h"
22 #include "api/peer_connection_interface.h"
23 #include "api/rtc_error.h"
24 #include "api/scoped_refptr.h"
25 #include "api/task_queue/default_task_queue_factory.h"
26 #include "api/task_queue/task_queue_factory.h"
27 #include "media/base/fake_media_engine.h"
28 #include "media/base/media_engine.h"
29 #include "p2p/base/mock_async_resolver.h"
30 #include "p2p/base/port_allocator.h"
31 #include "p2p/client/basic_port_allocator.h"
32 #include "pc/peer_connection.h"
33 #include "pc/peer_connection_factory.h"
34 #include "pc/peer_connection_proxy.h"
35 #include "pc/peer_connection_wrapper.h"
36 #include "pc/sdp_utils.h"
37 #include "pc/test/mock_peer_connection_observers.h"
38 #include "pc/usage_pattern.h"
39 #include "pc/webrtc_sdp.h"
40 #include "rtc_base/arraysize.h"
41 #include "rtc_base/checks.h"
42 #include "rtc_base/fake_mdns_responder.h"
43 #include "rtc_base/fake_network.h"
44 #include "rtc_base/gunit.h"
45 #include "rtc_base/mdns_responder_interface.h"
46 #include "rtc_base/socket_address.h"
47 #include "rtc_base/thread.h"
48 #include "rtc_base/virtual_socket_server.h"
49 #include "system_wrappers/include/metrics.h"
50 #include "test/gmock.h"
51 #include "test/gtest.h"
52 
53 namespace webrtc {
54 
55 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
56 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
57 using ::testing::NiceMock;
58 using ::testing::Values;
59 
60 static const char kUsagePatternMetric[] = "WebRTC.PeerConnection.UsagePattern";
61 static constexpr int kDefaultTimeout = 10000;
62 static const rtc::SocketAddress kLocalAddrs[2] = {
63     rtc::SocketAddress("1.1.1.1", 0), rtc::SocketAddress("2.2.2.2", 0)};
64 static const rtc::SocketAddress kPrivateLocalAddress("10.1.1.1", 0);
65 static const rtc::SocketAddress kPrivateIpv6LocalAddress("fd12:3456:789a:1::1",
66                                                          0);
67 
MakeUsageFingerprint(std::set<UsageEvent> events)68 int MakeUsageFingerprint(std::set<UsageEvent> events) {
69   int signature = 0;
70   for (const auto it : events) {
71     signature |= static_cast<int>(it);
72   }
73   return signature;
74 }
75 
76 class PeerConnectionFactoryForUsageHistogramTest
77     : public PeerConnectionFactory {
78  public:
PeerConnectionFactoryForUsageHistogramTest()79   PeerConnectionFactoryForUsageHistogramTest()
80       : PeerConnectionFactory([] {
81           PeerConnectionFactoryDependencies dependencies;
82           dependencies.network_thread = rtc::Thread::Current();
83           dependencies.worker_thread = rtc::Thread::Current();
84           dependencies.signaling_thread = rtc::Thread::Current();
85           dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
86           dependencies.media_engine =
87               std::make_unique<cricket::FakeMediaEngine>();
88           dependencies.call_factory = CreateCallFactory();
89           return dependencies;
90         }()) {}
91 };
92 
93 class PeerConnectionWrapperForUsageHistogramTest;
94 
95 typedef PeerConnectionWrapperForUsageHistogramTest* RawWrapperPtr;
96 
97 class ObserverForUsageHistogramTest : public MockPeerConnectionObserver {
98  public:
99   void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
100 
OnInterestingUsage(int usage_pattern)101   void OnInterestingUsage(int usage_pattern) override {
102     interesting_usage_detected_ = usage_pattern;
103   }
104 
PrepareToExchangeCandidates(RawWrapperPtr other)105   void PrepareToExchangeCandidates(RawWrapperPtr other) {
106     candidate_target_ = other;
107   }
108 
HaveDataChannel()109   bool HaveDataChannel() { return last_datachannel_ != nullptr; }
110 
interesting_usage_detected()111   absl::optional<int> interesting_usage_detected() {
112     return interesting_usage_detected_;
113   }
114 
ClearInterestingUsageDetector()115   void ClearInterestingUsageDetector() {
116     interesting_usage_detected_ = absl::optional<int>();
117   }
118 
candidate_gathered() const119   bool candidate_gathered() const { return candidate_gathered_; }
120 
121  private:
122   absl::optional<int> interesting_usage_detected_;
123   bool candidate_gathered_ = false;
124   RawWrapperPtr candidate_target_;  // Note: Not thread-safe against deletions.
125 };
126 
127 class PeerConnectionWrapperForUsageHistogramTest
128     : public PeerConnectionWrapper {
129  public:
130   using PeerConnectionWrapper::PeerConnectionWrapper;
131 
GetInternalPeerConnection()132   PeerConnection* GetInternalPeerConnection() {
133     auto* pci =
134         static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
135             pc());
136     return static_cast<PeerConnection*>(pci->internal());
137   }
138 
139   // Override with different return type
observer()140   ObserverForUsageHistogramTest* observer() {
141     return static_cast<ObserverForUsageHistogramTest*>(
142         PeerConnectionWrapper::observer());
143   }
144 
PrepareToExchangeCandidates(PeerConnectionWrapperForUsageHistogramTest * other)145   void PrepareToExchangeCandidates(
146       PeerConnectionWrapperForUsageHistogramTest* other) {
147     observer()->PrepareToExchangeCandidates(other);
148     other->observer()->PrepareToExchangeCandidates(this);
149   }
150 
IsConnected()151   bool IsConnected() {
152     return pc()->ice_connection_state() ==
153                PeerConnectionInterface::kIceConnectionConnected ||
154            pc()->ice_connection_state() ==
155                PeerConnectionInterface::kIceConnectionCompleted;
156   }
157 
HaveDataChannel()158   bool HaveDataChannel() {
159     return static_cast<ObserverForUsageHistogramTest*>(observer())
160         ->HaveDataChannel();
161   }
BufferIceCandidate(const webrtc::IceCandidateInterface * candidate)162   void BufferIceCandidate(const webrtc::IceCandidateInterface* candidate) {
163     std::string sdp;
164     EXPECT_TRUE(candidate->ToString(&sdp));
165     std::unique_ptr<webrtc::IceCandidateInterface> candidate_copy(
166         CreateIceCandidate(candidate->sdp_mid(), candidate->sdp_mline_index(),
167                            sdp, nullptr));
168     buffered_candidates_.push_back(std::move(candidate_copy));
169   }
170 
AddBufferedIceCandidates()171   void AddBufferedIceCandidates() {
172     for (const auto& candidate : buffered_candidates_) {
173       EXPECT_TRUE(pc()->AddIceCandidate(candidate.get()));
174     }
175     buffered_candidates_.clear();
176   }
177 
178   // This method performs the following actions in sequence:
179   // 1. Exchange Offer and Answer.
180   // 2. Exchange ICE candidates after both caller and callee complete
181   // gathering.
182   // 3. Wait for ICE to connect.
183   //
184   // This guarantees a deterministic sequence of events and also rules out the
185   // occurrence of prflx candidates if the offer/answer signaling and the
186   // candidate trickling race in order. In case prflx candidates need to be
187   // simulated, see the approach used by tests below for that.
ConnectTo(PeerConnectionWrapperForUsageHistogramTest * callee)188   bool ConnectTo(PeerConnectionWrapperForUsageHistogramTest* callee) {
189     PrepareToExchangeCandidates(callee);
190     if (!ExchangeOfferAnswerWith(callee)) {
191       return false;
192     }
193     // Wait until the gathering completes before we signal the candidate.
194     WAIT(observer()->ice_gathering_complete_, kDefaultTimeout);
195     WAIT(callee->observer()->ice_gathering_complete_, kDefaultTimeout);
196     AddBufferedIceCandidates();
197     callee->AddBufferedIceCandidates();
198     WAIT(IsConnected(), kDefaultTimeout);
199     WAIT(callee->IsConnected(), kDefaultTimeout);
200     return IsConnected() && callee->IsConnected();
201   }
202 
GenerateOfferAndCollectCandidates()203   bool GenerateOfferAndCollectCandidates() {
204     auto offer = CreateOffer(RTCOfferAnswerOptions());
205     if (!offer) {
206       return false;
207     }
208     bool set_local_offer =
209         SetLocalDescription(CloneSessionDescription(offer.get()));
210     EXPECT_TRUE(set_local_offer);
211     if (!set_local_offer) {
212       return false;
213     }
214     EXPECT_TRUE_WAIT(observer()->ice_gathering_complete_, kDefaultTimeout);
215     return true;
216   }
217 
ice_gathering_state()218   webrtc::PeerConnectionInterface::IceGatheringState ice_gathering_state() {
219     return pc()->ice_gathering_state();
220   }
221 
222  private:
223   // Candidates that have been sent but not yet configured
224   std::vector<std::unique_ptr<webrtc::IceCandidateInterface>>
225       buffered_candidates_;
226 };
227 
228 // Buffers candidates until we add them via AddBufferedIceCandidates.
OnIceCandidate(const webrtc::IceCandidateInterface * candidate)229 void ObserverForUsageHistogramTest::OnIceCandidate(
230     const webrtc::IceCandidateInterface* candidate) {
231   // If target is not set, ignore. This happens in one-ended unit tests.
232   if (candidate_target_) {
233     this->candidate_target_->BufferIceCandidate(candidate);
234   }
235   candidate_gathered_ = true;
236 }
237 
238 class PeerConnectionUsageHistogramTest : public ::testing::Test {
239  protected:
240   typedef std::unique_ptr<PeerConnectionWrapperForUsageHistogramTest>
241       WrapperPtr;
242 
PeerConnectionUsageHistogramTest()243   PeerConnectionUsageHistogramTest()
244       : vss_(new rtc::VirtualSocketServer()), main_(vss_.get()) {
245     webrtc::metrics::Reset();
246   }
247 
CreatePeerConnection()248   WrapperPtr CreatePeerConnection() {
249     RTCConfiguration config;
250     config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
251     return CreatePeerConnection(
252         config, PeerConnectionFactoryInterface::Options(), nullptr);
253   }
254 
CreatePeerConnection(const RTCConfiguration & config)255   WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
256     return CreatePeerConnection(
257         config, PeerConnectionFactoryInterface::Options(), nullptr);
258   }
259 
CreatePeerConnectionWithMdns(const RTCConfiguration & config)260   WrapperPtr CreatePeerConnectionWithMdns(const RTCConfiguration& config) {
261     auto resolver_factory =
262         std::make_unique<NiceMock<webrtc::MockAsyncResolverFactory>>();
263 
264     webrtc::PeerConnectionDependencies deps(nullptr /* observer_in */);
265 
266     auto fake_network = NewFakeNetwork();
267     fake_network->set_mdns_responder(
268         std::make_unique<webrtc::FakeMdnsResponder>(rtc::Thread::Current()));
269     fake_network->AddInterface(NextLocalAddress());
270 
271     std::unique_ptr<cricket::BasicPortAllocator> port_allocator(
272         new cricket::BasicPortAllocator(
273             fake_network,
274             std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get())));
275 
276     deps.async_resolver_factory = std::move(resolver_factory);
277     deps.allocator = std::move(port_allocator);
278 
279     return CreatePeerConnection(
280         config, PeerConnectionFactoryInterface::Options(), std::move(deps));
281   }
282 
CreatePeerConnectionWithImmediateReport()283   WrapperPtr CreatePeerConnectionWithImmediateReport() {
284     RTCConfiguration configuration;
285     configuration.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
286     configuration.report_usage_pattern_delay_ms = 0;
287     return CreatePeerConnection(
288         configuration, PeerConnectionFactoryInterface::Options(), nullptr);
289   }
290 
CreatePeerConnectionWithPrivateLocalAddresses()291   WrapperPtr CreatePeerConnectionWithPrivateLocalAddresses() {
292     auto* fake_network = NewFakeNetwork();
293     fake_network->AddInterface(NextLocalAddress());
294     fake_network->AddInterface(kPrivateLocalAddress);
295 
296     auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
297         fake_network,
298         std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
299     RTCConfiguration config;
300     config.sdp_semantics = SdpSemantics::kUnifiedPlan;
301     return CreatePeerConnection(config,
302                                 PeerConnectionFactoryInterface::Options(),
303                                 std::move(port_allocator));
304   }
305 
CreatePeerConnectionWithPrivateIpv6LocalAddresses()306   WrapperPtr CreatePeerConnectionWithPrivateIpv6LocalAddresses() {
307     auto* fake_network = NewFakeNetwork();
308     fake_network->AddInterface(NextLocalAddress());
309     fake_network->AddInterface(kPrivateIpv6LocalAddress);
310 
311     auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
312         fake_network,
313         std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
314 
315     RTCConfiguration config;
316     config.sdp_semantics = SdpSemantics::kUnifiedPlan;
317     return CreatePeerConnection(config,
318                                 PeerConnectionFactoryInterface::Options(),
319                                 std::move(port_allocator));
320   }
321 
CreatePeerConnection(const RTCConfiguration & config,const PeerConnectionFactoryInterface::Options factory_options,std::unique_ptr<cricket::PortAllocator> allocator)322   WrapperPtr CreatePeerConnection(
323       const RTCConfiguration& config,
324       const PeerConnectionFactoryInterface::Options factory_options,
325       std::unique_ptr<cricket::PortAllocator> allocator) {
326     PeerConnectionDependencies deps(nullptr);
327     deps.allocator = std::move(allocator);
328 
329     return CreatePeerConnection(config, factory_options, std::move(deps));
330   }
331 
CreatePeerConnection(const RTCConfiguration & config,const PeerConnectionFactoryInterface::Options factory_options,PeerConnectionDependencies deps)332   WrapperPtr CreatePeerConnection(
333       const RTCConfiguration& config,
334       const PeerConnectionFactoryInterface::Options factory_options,
335       PeerConnectionDependencies deps) {
336     auto pc_factory =
337         rtc::make_ref_counted<PeerConnectionFactoryForUsageHistogramTest>();
338     pc_factory->SetOptions(factory_options);
339 
340     // If no allocator is provided, one will be created using a network manager
341     // that uses the host network. This doesn't work on all trybots.
342     if (!deps.allocator) {
343       auto fake_network = NewFakeNetwork();
344       fake_network->AddInterface(NextLocalAddress());
345       deps.allocator = std::make_unique<cricket::BasicPortAllocator>(
346           fake_network,
347           std::make_unique<rtc::BasicPacketSocketFactory>(vss_.get()));
348     }
349 
350     auto observer = std::make_unique<ObserverForUsageHistogramTest>();
351     deps.observer = observer.get();
352 
353     auto result =
354         pc_factory->CreatePeerConnectionOrError(config, std::move(deps));
355     if (!result.ok()) {
356       return nullptr;
357     }
358 
359     observer->SetPeerConnectionInterface(result.value().get());
360     auto wrapper = std::make_unique<PeerConnectionWrapperForUsageHistogramTest>(
361         pc_factory, result.MoveValue(), std::move(observer));
362     return wrapper;
363   }
364 
ObservedFingerprint()365   int ObservedFingerprint() {
366     // This works correctly only if there is only one sample value
367     // that has been counted.
368     // Returns -1 for "not found".
369     return webrtc::metrics::MinSample(kUsagePatternMetric);
370   }
371 
372   // The PeerConnection's port allocator is tied to the PeerConnection's
373   // lifetime and expects the underlying NetworkManager to outlive it.  That
374   // prevents us from having the PeerConnectionWrapper own the fake network.
375   // Therefore, the test fixture will own all the fake networks even though
376   // tests should access the fake network through the PeerConnectionWrapper.
NewFakeNetwork()377   rtc::FakeNetworkManager* NewFakeNetwork() {
378     fake_networks_.emplace_back(std::make_unique<rtc::FakeNetworkManager>());
379     return fake_networks_.back().get();
380   }
381 
NextLocalAddress()382   rtc::SocketAddress NextLocalAddress() {
383     RTC_DCHECK(next_local_address_ < (int)arraysize(kLocalAddrs));
384     return kLocalAddrs[next_local_address_++];
385   }
386 
387   std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
388   int next_local_address_ = 0;
389   std::unique_ptr<rtc::VirtualSocketServer> vss_;
390   rtc::AutoSocketServerThread main_;
391 };
392 
TEST_F(PeerConnectionUsageHistogramTest,UsageFingerprintHistogramFromTimeout)393 TEST_F(PeerConnectionUsageHistogramTest, UsageFingerprintHistogramFromTimeout) {
394   auto pc = CreatePeerConnectionWithImmediateReport();
395 
396   int expected_fingerprint = MakeUsageFingerprint({});
397   EXPECT_METRIC_EQ_WAIT(1, webrtc::metrics::NumSamples(kUsagePatternMetric),
398                         kDefaultTimeout);
399   EXPECT_METRIC_EQ(
400       1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
401 }
402 
403 #ifndef WEBRTC_ANDROID
404 // These tests do not work on Android. Why is unclear.
405 // https://bugs.webrtc.org/9461
406 
407 // Test getting the usage fingerprint for an audio/video connection.
TEST_F(PeerConnectionUsageHistogramTest,FingerprintAudioVideo)408 TEST_F(PeerConnectionUsageHistogramTest, FingerprintAudioVideo) {
409   auto caller = CreatePeerConnection();
410   auto callee = CreatePeerConnection();
411   caller->AddAudioTrack("audio");
412   caller->AddVideoTrack("video");
413   ASSERT_TRUE(caller->ConnectTo(callee.get()));
414   caller->pc()->Close();
415   callee->pc()->Close();
416   int expected_fingerprint = MakeUsageFingerprint(
417       {UsageEvent::AUDIO_ADDED, UsageEvent::VIDEO_ADDED,
418        UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
419        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
420        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
421        UsageEvent::ICE_STATE_CONNECTED, UsageEvent::REMOTE_CANDIDATE_ADDED,
422        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
423   // In this case, we may or may not have PRIVATE_CANDIDATE_COLLECTED,
424   // depending on the machine configuration.
425   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
426   EXPECT_METRIC_TRUE(
427       webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint) ==
428           2 ||
429       webrtc::metrics::NumEvents(
430           kUsagePatternMetric,
431           expected_fingerprint |
432               static_cast<int>(UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) == 2);
433 }
434 
435 // Test getting the usage fingerprint when the caller collects an mDNS
436 // candidate.
TEST_F(PeerConnectionUsageHistogramTest,FingerprintWithMdnsCaller)437 TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCaller) {
438   RTCConfiguration config;
439   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
440 
441   // Enable hostname candidates with mDNS names.
442   auto caller = CreatePeerConnectionWithMdns(config);
443   auto callee = CreatePeerConnection(config);
444 
445   caller->AddAudioTrack("audio");
446   caller->AddVideoTrack("video");
447   ASSERT_TRUE(caller->ConnectTo(callee.get()));
448   caller->pc()->Close();
449   callee->pc()->Close();
450 
451   int expected_fingerprint_caller = MakeUsageFingerprint(
452       {UsageEvent::AUDIO_ADDED, UsageEvent::VIDEO_ADDED,
453        UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
454        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
455        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::MDNS_CANDIDATE_COLLECTED,
456        UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, UsageEvent::ICE_STATE_CONNECTED,
457        UsageEvent::REMOTE_CANDIDATE_ADDED,
458        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
459 
460   // Without a resolver, the callee cannot resolve the received mDNS candidate
461   // but can still connect with the caller via a prflx candidate. As a result,
462   // the bit for the direct connection should not be logged.
463   int expected_fingerprint_callee = MakeUsageFingerprint(
464       {UsageEvent::AUDIO_ADDED, UsageEvent::VIDEO_ADDED,
465        UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
466        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
467        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
468        UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED, UsageEvent::ICE_STATE_CONNECTED,
469        UsageEvent::REMOTE_CANDIDATE_ADDED, UsageEvent::CLOSE_CALLED});
470   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
471   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
472                                                  expected_fingerprint_caller));
473   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
474                                                  expected_fingerprint_callee));
475 }
476 
477 // Test getting the usage fingerprint when the callee collects an mDNS
478 // candidate.
TEST_F(PeerConnectionUsageHistogramTest,FingerprintWithMdnsCallee)479 TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCallee) {
480   RTCConfiguration config;
481   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
482 
483   // Enable hostname candidates with mDNS names.
484   auto caller = CreatePeerConnection(config);
485   auto callee = CreatePeerConnectionWithMdns(config);
486 
487   caller->AddAudioTrack("audio");
488   caller->AddVideoTrack("video");
489   ASSERT_TRUE(caller->ConnectTo(callee.get()));
490   caller->pc()->Close();
491   callee->pc()->Close();
492 
493   // Similar to the test above, the caller connects with the callee via a prflx
494   // candidate.
495   int expected_fingerprint_caller = MakeUsageFingerprint(
496       {UsageEvent::AUDIO_ADDED, UsageEvent::VIDEO_ADDED,
497        UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
498        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
499        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
500        UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED, UsageEvent::ICE_STATE_CONNECTED,
501        UsageEvent::REMOTE_CANDIDATE_ADDED, UsageEvent::CLOSE_CALLED});
502 
503   int expected_fingerprint_callee = MakeUsageFingerprint(
504       {UsageEvent::AUDIO_ADDED, UsageEvent::VIDEO_ADDED,
505        UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
506        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
507        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::MDNS_CANDIDATE_COLLECTED,
508        UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, UsageEvent::ICE_STATE_CONNECTED,
509        UsageEvent::REMOTE_CANDIDATE_ADDED,
510        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
511   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
512   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
513                                                  expected_fingerprint_caller));
514   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
515                                                  expected_fingerprint_callee));
516 }
517 
518 #ifdef WEBRTC_HAVE_SCTP
TEST_F(PeerConnectionUsageHistogramTest,FingerprintDataOnly)519 TEST_F(PeerConnectionUsageHistogramTest, FingerprintDataOnly) {
520   auto caller = CreatePeerConnection();
521   auto callee = CreatePeerConnection();
522   caller->CreateDataChannel("foodata");
523   ASSERT_TRUE(caller->ConnectTo(callee.get()));
524   ASSERT_TRUE_WAIT(callee->HaveDataChannel(), kDefaultTimeout);
525   caller->pc()->Close();
526   callee->pc()->Close();
527   int expected_fingerprint = MakeUsageFingerprint(
528       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
529        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
530        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
531        UsageEvent::ICE_STATE_CONNECTED, UsageEvent::REMOTE_CANDIDATE_ADDED,
532        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
533   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
534   EXPECT_METRIC_TRUE(
535       webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint) ==
536           2 ||
537       webrtc::metrics::NumEvents(
538           kUsagePatternMetric,
539           expected_fingerprint |
540               static_cast<int>(UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) == 2);
541 }
542 #endif  // WEBRTC_HAVE_SCTP
543 #endif  // WEBRTC_ANDROID
544 
TEST_F(PeerConnectionUsageHistogramTest,FingerprintStunTurn)545 TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurn) {
546   RTCConfiguration configuration;
547   configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
548   PeerConnection::IceServer server;
549   server.urls = {"stun:dummy.stun.server"};
550   configuration.servers.push_back(server);
551   server.urls = {"turn:dummy.turn.server"};
552   server.username = "username";
553   server.password = "password";
554   configuration.servers.push_back(server);
555   auto caller = CreatePeerConnection(configuration);
556   ASSERT_TRUE(caller);
557   caller->pc()->Close();
558   int expected_fingerprint = MakeUsageFingerprint(
559       {UsageEvent::STUN_SERVER_ADDED, UsageEvent::TURN_SERVER_ADDED,
560        UsageEvent::CLOSE_CALLED});
561   EXPECT_METRIC_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
562   EXPECT_METRIC_EQ(
563       1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
564 }
565 
TEST_F(PeerConnectionUsageHistogramTest,FingerprintStunTurnInReconfiguration)566 TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurnInReconfiguration) {
567   RTCConfiguration configuration;
568   configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
569   PeerConnection::IceServer server;
570   server.urls = {"stun:dummy.stun.server"};
571   configuration.servers.push_back(server);
572   server.urls = {"turn:dummy.turn.server"};
573   server.username = "username";
574   server.password = "password";
575   configuration.servers.push_back(server);
576   auto caller = CreatePeerConnection();
577   ASSERT_TRUE(caller);
578   ASSERT_TRUE(caller->pc()->SetConfiguration(configuration).ok());
579   caller->pc()->Close();
580   int expected_fingerprint = MakeUsageFingerprint(
581       {UsageEvent::STUN_SERVER_ADDED, UsageEvent::TURN_SERVER_ADDED,
582        UsageEvent::CLOSE_CALLED});
583   EXPECT_METRIC_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
584   EXPECT_METRIC_EQ(
585       1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
586 }
587 
TEST_F(PeerConnectionUsageHistogramTest,FingerprintWithPrivateIPCaller)588 TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCaller) {
589   auto caller = CreatePeerConnectionWithPrivateLocalAddresses();
590   auto callee = CreatePeerConnection();
591   caller->AddAudioTrack("audio");
592   ASSERT_TRUE(caller->ConnectTo(callee.get()));
593   caller->pc()->Close();
594   callee->pc()->Close();
595 
596   int expected_fingerprint_caller = MakeUsageFingerprint(
597       {UsageEvent::AUDIO_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
598        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
599        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::PRIVATE_CANDIDATE_COLLECTED,
600        UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, UsageEvent::ICE_STATE_CONNECTED,
601        UsageEvent::REMOTE_CANDIDATE_ADDED,
602        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
603 
604   int expected_fingerprint_callee = MakeUsageFingerprint(
605       {UsageEvent::AUDIO_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
606        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
607        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
608        UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED,
609        UsageEvent::ICE_STATE_CONNECTED, UsageEvent::REMOTE_CANDIDATE_ADDED,
610        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
611   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
612   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
613                                                  expected_fingerprint_caller));
614   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
615                                                  expected_fingerprint_callee));
616 }
617 
TEST_F(PeerConnectionUsageHistogramTest,FingerprintWithPrivateIpv6Callee)618 TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIpv6Callee) {
619   auto caller = CreatePeerConnection();
620   auto callee = CreatePeerConnectionWithPrivateIpv6LocalAddresses();
621   caller->AddAudioTrack("audio");
622   ASSERT_TRUE(caller->ConnectTo(callee.get()));
623   caller->pc()->Close();
624   callee->pc()->Close();
625 
626   int expected_fingerprint_caller = MakeUsageFingerprint(
627       {UsageEvent::AUDIO_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
628        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
629        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
630        UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED,
631        UsageEvent::ICE_STATE_CONNECTED, UsageEvent::REMOTE_CANDIDATE_ADDED,
632        UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED,
633        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
634 
635   int expected_fingerprint_callee = MakeUsageFingerprint(
636       {UsageEvent::AUDIO_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
637        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
638        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::PRIVATE_CANDIDATE_COLLECTED,
639        UsageEvent::IPV6_CANDIDATE_COLLECTED,
640        UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED,
641        UsageEvent::REMOTE_CANDIDATE_ADDED, UsageEvent::ICE_STATE_CONNECTED,
642        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
643   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
644   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
645                                                  expected_fingerprint_caller));
646   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
647                                                  expected_fingerprint_callee));
648 }
649 
650 #ifndef WEBRTC_ANDROID
651 #ifdef WEBRTC_HAVE_SCTP
652 // Test that the usage pattern bits for adding remote (private IPv6) candidates
653 // are set when the remote candidates are retrieved from the Offer SDP instead
654 // of trickled ICE messages.
TEST_F(PeerConnectionUsageHistogramTest,AddRemoteCandidatesFromRemoteDescription)655 TEST_F(PeerConnectionUsageHistogramTest,
656        AddRemoteCandidatesFromRemoteDescription) {
657   // We construct the following data-channel-only scenario. The caller collects
658   // IPv6 private local candidates and appends them in the Offer as in
659   // non-trickled sessions. The callee collects mDNS candidates that are not
660   // contained in the Answer as in Trickle ICE. Only the Offer and Answer are
661   // signaled and we expect a connection with prflx remote candidates at the
662   // caller side.
663   auto caller = CreatePeerConnectionWithPrivateIpv6LocalAddresses();
664   RTCConfiguration config;
665   config.sdp_semantics = SdpSemantics::kUnifiedPlan;
666   auto callee = CreatePeerConnectionWithMdns(config);
667   caller->CreateDataChannel("test_channel");
668   ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
669   // Wait until the gathering completes so that the session description would
670   // have contained ICE candidates.
671   EXPECT_EQ_WAIT(webrtc::PeerConnectionInterface::kIceGatheringComplete,
672                  caller->ice_gathering_state(), kDefaultTimeout);
673   EXPECT_TRUE(caller->observer()->candidate_gathered());
674   // Get the current offer that contains candidates and pass it to the callee.
675   //
676   // Note that we cannot use CloneSessionDescription on `cur_offer` to obtain an
677   // SDP with candidates. The method above does not strictly copy everything, in
678   // particular, not copying the ICE candidates.
679   // TODO(qingsi): Technically, this is a bug. Fix it.
680   auto cur_offer = caller->pc()->local_description();
681   ASSERT_TRUE(cur_offer);
682   std::string sdp_with_candidates_str;
683   cur_offer->ToString(&sdp_with_candidates_str);
684   auto offer = std::make_unique<JsepSessionDescription>(SdpType::kOffer);
685   ASSERT_TRUE(SdpDeserialize(sdp_with_candidates_str, offer.get(),
686                              nullptr /* error */));
687   ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
688 
689   // By default, the Answer created does not contain ICE candidates.
690   auto answer = callee->CreateAnswer();
691   callee->SetLocalDescription(CloneSessionDescription(answer.get()));
692   caller->SetRemoteDescription(std::move(answer));
693   EXPECT_TRUE_WAIT(caller->IsConnected(), kDefaultTimeout);
694   EXPECT_TRUE_WAIT(callee->IsConnected(), kDefaultTimeout);
695   // The callee needs to process the open message to have the data channel open.
696   EXPECT_TRUE_WAIT(callee->observer()->last_datachannel_ != nullptr,
697                    kDefaultTimeout);
698   caller->pc()->Close();
699   callee->pc()->Close();
700 
701   // The caller should not have added any remote candidate either via
702   // AddIceCandidate or from the remote description. Also, the caller connects
703   // with the callee via a prflx candidate and hence no direct connection bit
704   // should be set.
705   int expected_fingerprint_caller = MakeUsageFingerprint(
706       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
707        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
708        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::PRIVATE_CANDIDATE_COLLECTED,
709        UsageEvent::IPV6_CANDIDATE_COLLECTED, UsageEvent::ICE_STATE_CONNECTED,
710        UsageEvent::CLOSE_CALLED});
711 
712   int expected_fingerprint_callee = MakeUsageFingerprint(
713       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
714        UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED,
715        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::MDNS_CANDIDATE_COLLECTED,
716        UsageEvent::REMOTE_CANDIDATE_ADDED,
717        UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED,
718        UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED, UsageEvent::ICE_STATE_CONNECTED,
719        UsageEvent::DIRECT_CONNECTION_SELECTED, UsageEvent::CLOSE_CALLED});
720   EXPECT_METRIC_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
721   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
722                                                  expected_fingerprint_caller));
723   EXPECT_METRIC_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
724                                                  expected_fingerprint_callee));
725 }
726 
TEST_F(PeerConnectionUsageHistogramTest,NotableUsageNoted)727 TEST_F(PeerConnectionUsageHistogramTest, NotableUsageNoted) {
728   auto caller = CreatePeerConnection();
729   caller->CreateDataChannel("foo");
730   caller->GenerateOfferAndCollectCandidates();
731   caller->pc()->Close();
732   int expected_fingerprint = MakeUsageFingerprint(
733       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
734        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::CLOSE_CALLED});
735   EXPECT_METRIC_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
736   EXPECT_METRIC_TRUE(
737       expected_fingerprint == ObservedFingerprint() ||
738       (expected_fingerprint |
739        static_cast<int>(UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
740           ObservedFingerprint());
741   EXPECT_METRIC_EQ(absl::make_optional(ObservedFingerprint()),
742                    caller->observer()->interesting_usage_detected());
743 }
744 
TEST_F(PeerConnectionUsageHistogramTest,NotableUsageOnEventFiring)745 TEST_F(PeerConnectionUsageHistogramTest, NotableUsageOnEventFiring) {
746   auto caller = CreatePeerConnection();
747   caller->CreateDataChannel("foo");
748   caller->GenerateOfferAndCollectCandidates();
749   int expected_fingerprint = MakeUsageFingerprint(
750       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
751        UsageEvent::CANDIDATE_COLLECTED});
752   EXPECT_METRIC_EQ(0, webrtc::metrics::NumSamples(kUsagePatternMetric));
753   caller->GetInternalPeerConnection()->RequestUsagePatternReportForTesting();
754   EXPECT_METRIC_EQ_WAIT(1, webrtc::metrics::NumSamples(kUsagePatternMetric),
755                         kDefaultTimeout);
756   EXPECT_METRIC_TRUE(
757       expected_fingerprint == ObservedFingerprint() ||
758       (expected_fingerprint |
759        static_cast<int>(UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
760           ObservedFingerprint());
761   EXPECT_METRIC_EQ(absl::make_optional(ObservedFingerprint()),
762                    caller->observer()->interesting_usage_detected());
763 }
764 
TEST_F(PeerConnectionUsageHistogramTest,NoNotableUsageOnEventFiringAfterClose)765 TEST_F(PeerConnectionUsageHistogramTest,
766        NoNotableUsageOnEventFiringAfterClose) {
767   auto caller = CreatePeerConnection();
768   caller->CreateDataChannel("foo");
769   caller->GenerateOfferAndCollectCandidates();
770   int expected_fingerprint = MakeUsageFingerprint(
771       {UsageEvent::DATA_ADDED, UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED,
772        UsageEvent::CANDIDATE_COLLECTED, UsageEvent::CLOSE_CALLED});
773   EXPECT_METRIC_EQ(0, webrtc::metrics::NumSamples(kUsagePatternMetric));
774   caller->pc()->Close();
775   EXPECT_METRIC_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
776   caller->GetInternalPeerConnection()->RequestUsagePatternReportForTesting();
777   caller->observer()->ClearInterestingUsageDetector();
778   EXPECT_METRIC_EQ_WAIT(2, webrtc::metrics::NumSamples(kUsagePatternMetric),
779                         kDefaultTimeout);
780   EXPECT_METRIC_TRUE(
781       expected_fingerprint == ObservedFingerprint() ||
782       (expected_fingerprint |
783        static_cast<int>(UsageEvent::PRIVATE_CANDIDATE_COLLECTED)) ==
784           ObservedFingerprint());
785   // After close, the usage-detection callback should NOT have been called.
786   EXPECT_METRIC_FALSE(caller->observer()->interesting_usage_detected());
787 }
788 #endif
789 #endif
790 
791 }  // namespace webrtc
792