xref: /aosp_15_r20/external/webrtc/pc/test/fake_peer_connection_for_stats.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2018 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 #ifndef PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
12 #define PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
13 
14 #include <map>
15 #include <memory>
16 #include <set>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 #include "media/base/fake_media_engine.h"
22 #include "pc/channel.h"
23 #include "pc/stream_collection.h"
24 #include "pc/test/fake_data_channel_controller.h"
25 #include "pc/test/fake_peer_connection_base.h"
26 
27 namespace webrtc {
28 
29 // Fake VoiceMediaChannel where the result of GetStats can be configured.
30 class FakeVoiceMediaChannelForStats : public cricket::FakeVoiceMediaChannel {
31  public:
FakeVoiceMediaChannelForStats(TaskQueueBase * network_thread)32   explicit FakeVoiceMediaChannelForStats(TaskQueueBase* network_thread)
33       : cricket::FakeVoiceMediaChannel(nullptr,
34                                        cricket::AudioOptions(),
35                                        network_thread) {}
36 
SetStats(const cricket::VoiceMediaInfo & voice_info)37   void SetStats(const cricket::VoiceMediaInfo& voice_info) {
38     stats_ = voice_info;
39   }
40 
41   // VoiceMediaChannel overrides.
GetStats(cricket::VoiceMediaInfo * info,bool get_and_clear_legacy_stats)42   bool GetStats(cricket::VoiceMediaInfo* info,
43                 bool get_and_clear_legacy_stats) override {
44     if (stats_) {
45       *info = *stats_;
46       return true;
47     }
48     return false;
49   }
50 
51  private:
52   absl::optional<cricket::VoiceMediaInfo> stats_;
53 };
54 
55 // Fake VideoMediaChannel where the result of GetStats can be configured.
56 class FakeVideoMediaChannelForStats : public cricket::FakeVideoMediaChannel {
57  public:
FakeVideoMediaChannelForStats(TaskQueueBase * network_thread)58   explicit FakeVideoMediaChannelForStats(TaskQueueBase* network_thread)
59       : cricket::FakeVideoMediaChannel(nullptr,
60                                        cricket::VideoOptions(),
61                                        network_thread) {}
62 
SetStats(const cricket::VideoMediaInfo & video_info)63   void SetStats(const cricket::VideoMediaInfo& video_info) {
64     stats_ = video_info;
65   }
66 
67   // VideoMediaChannel overrides.
GetStats(cricket::VideoMediaInfo * info)68   bool GetStats(cricket::VideoMediaInfo* info) override {
69     if (stats_) {
70       *info = *stats_;
71       return true;
72     }
73     return false;
74   }
75 
76  private:
77   absl::optional<cricket::VideoMediaInfo> stats_;
78 };
79 
80 constexpr bool kDefaultRtcpMuxRequired = true;
81 constexpr bool kDefaultSrtpRequired = true;
82 
83 class VoiceChannelForTesting : public cricket::VoiceChannel {
84  public:
VoiceChannelForTesting(rtc::Thread * worker_thread,rtc::Thread * network_thread,rtc::Thread * signaling_thread,std::unique_ptr<cricket::VoiceMediaChannel> channel,const std::string & content_name,bool srtp_required,webrtc::CryptoOptions crypto_options,rtc::UniqueRandomIdGenerator * ssrc_generator,std::string transport_name)85   VoiceChannelForTesting(rtc::Thread* worker_thread,
86                          rtc::Thread* network_thread,
87                          rtc::Thread* signaling_thread,
88                          std::unique_ptr<cricket::VoiceMediaChannel> channel,
89                          const std::string& content_name,
90                          bool srtp_required,
91                          webrtc::CryptoOptions crypto_options,
92                          rtc::UniqueRandomIdGenerator* ssrc_generator,
93                          std::string transport_name)
94       : VoiceChannel(worker_thread,
95                      network_thread,
96                      signaling_thread,
97                      std::move(channel),
98                      content_name,
99                      srtp_required,
100                      std::move(crypto_options),
101                      ssrc_generator),
102         test_transport_name_(std::move(transport_name)) {}
103 
104  private:
transport_name()105   absl::string_view transport_name() const override {
106     return test_transport_name_;
107   }
108 
109   const std::string test_transport_name_;
110 };
111 
112 class VideoChannelForTesting : public cricket::VideoChannel {
113  public:
VideoChannelForTesting(rtc::Thread * worker_thread,rtc::Thread * network_thread,rtc::Thread * signaling_thread,std::unique_ptr<cricket::VideoMediaChannel> channel,const std::string & content_name,bool srtp_required,webrtc::CryptoOptions crypto_options,rtc::UniqueRandomIdGenerator * ssrc_generator,std::string transport_name)114   VideoChannelForTesting(rtc::Thread* worker_thread,
115                          rtc::Thread* network_thread,
116                          rtc::Thread* signaling_thread,
117                          std::unique_ptr<cricket::VideoMediaChannel> channel,
118                          const std::string& content_name,
119                          bool srtp_required,
120                          webrtc::CryptoOptions crypto_options,
121                          rtc::UniqueRandomIdGenerator* ssrc_generator,
122                          std::string transport_name)
123       : VideoChannel(worker_thread,
124                      network_thread,
125                      signaling_thread,
126                      std::move(channel),
127                      content_name,
128                      srtp_required,
129                      std::move(crypto_options),
130                      ssrc_generator),
131         test_transport_name_(std::move(transport_name)) {}
132 
133  private:
transport_name()134   absl::string_view transport_name() const override {
135     return test_transport_name_;
136   }
137 
138   const std::string test_transport_name_;
139 };
140 
141 // This class is intended to be fed into the StatsCollector and
142 // RTCStatsCollector so that the stats functionality can be unit tested.
143 // Individual tests can configure this fake as needed to simulate scenarios
144 // under which to test the stats collectors.
145 class FakePeerConnectionForStats : public FakePeerConnectionBase {
146  public:
147   // TODO(steveanton): Add support for specifying separate threads to test
148   // multi-threading correctness.
FakePeerConnectionForStats()149   FakePeerConnectionForStats()
150       : network_thread_(rtc::Thread::Current()),
151         worker_thread_(rtc::Thread::Current()),
152         signaling_thread_(rtc::Thread::Current()),
153         // TODO(hta): remove separate thread variables and use context.
154         dependencies_(MakeDependencies()),
155         context_(ConnectionContext::Create(&dependencies_)),
156         local_streams_(StreamCollection::Create()),
157         remote_streams_(StreamCollection::Create()) {}
158 
~FakePeerConnectionForStats()159   ~FakePeerConnectionForStats() {
160     for (auto transceiver : transceivers_) {
161       transceiver->internal()->ClearChannel();
162     }
163   }
164 
MakeDependencies()165   static PeerConnectionFactoryDependencies MakeDependencies() {
166     PeerConnectionFactoryDependencies dependencies;
167     dependencies.network_thread = rtc::Thread::Current();
168     dependencies.worker_thread = rtc::Thread::Current();
169     dependencies.signaling_thread = rtc::Thread::Current();
170     dependencies.media_engine = std::make_unique<cricket::FakeMediaEngine>();
171     return dependencies;
172   }
173 
mutable_local_streams()174   rtc::scoped_refptr<StreamCollection> mutable_local_streams() {
175     return local_streams_;
176   }
177 
mutable_remote_streams()178   rtc::scoped_refptr<StreamCollection> mutable_remote_streams() {
179     return remote_streams_;
180   }
181 
AddSender(rtc::scoped_refptr<RtpSenderInternal> sender)182   rtc::scoped_refptr<RtpSenderInterface> AddSender(
183       rtc::scoped_refptr<RtpSenderInternal> sender) {
184     // TODO(steveanton): Switch tests to use RtpTransceivers directly.
185     auto sender_proxy = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
186         signaling_thread_, sender);
187     GetOrCreateFirstTransceiverOfType(sender->media_type())
188         ->internal()
189         ->AddSender(sender_proxy);
190     return sender_proxy;
191   }
192 
RemoveSender(rtc::scoped_refptr<RtpSenderInterface> sender)193   void RemoveSender(rtc::scoped_refptr<RtpSenderInterface> sender) {
194     GetOrCreateFirstTransceiverOfType(sender->media_type())
195         ->internal()
196         ->RemoveSender(sender.get());
197   }
198 
AddReceiver(rtc::scoped_refptr<RtpReceiverInternal> receiver)199   rtc::scoped_refptr<RtpReceiverInterface> AddReceiver(
200       rtc::scoped_refptr<RtpReceiverInternal> receiver) {
201     // TODO(steveanton): Switch tests to use RtpTransceivers directly.
202     auto receiver_proxy =
203         RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
204             signaling_thread_, worker_thread_, receiver);
205     GetOrCreateFirstTransceiverOfType(receiver->media_type())
206         ->internal()
207         ->AddReceiver(receiver_proxy);
208     return receiver_proxy;
209   }
210 
RemoveReceiver(rtc::scoped_refptr<RtpReceiverInterface> receiver)211   void RemoveReceiver(rtc::scoped_refptr<RtpReceiverInterface> receiver) {
212     GetOrCreateFirstTransceiverOfType(receiver->media_type())
213         ->internal()
214         ->RemoveReceiver(receiver.get());
215   }
216 
217   FakeVoiceMediaChannelForStats* AddVoiceChannel(
218       const std::string& mid,
219       const std::string& transport_name,
220       cricket::VoiceMediaInfo initial_stats = cricket::VoiceMediaInfo()) {
221     auto voice_media_channel =
222         std::make_unique<FakeVoiceMediaChannelForStats>(network_thread_);
223     auto* voice_media_channel_ptr = voice_media_channel.get();
224     auto voice_channel = std::make_unique<VoiceChannelForTesting>(
225         worker_thread_, network_thread_, signaling_thread_,
226         std::move(voice_media_channel), mid, kDefaultSrtpRequired,
227         webrtc::CryptoOptions(), context_->ssrc_generator(), transport_name);
228     auto transceiver =
229         GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO)
230             ->internal();
231     if (transceiver->channel()) {
232       // This transceiver already has a channel, create a new one.
233       transceiver =
234           CreateTransceiverOfType(cricket::MEDIA_TYPE_AUDIO)->internal();
235     }
236     RTC_DCHECK(!transceiver->channel());
237     transceiver->SetChannel(std::move(voice_channel),
238                             [](const std::string&) { return nullptr; });
239     voice_media_channel_ptr->SetStats(initial_stats);
240     return voice_media_channel_ptr;
241   }
242 
243   FakeVideoMediaChannelForStats* AddVideoChannel(
244       const std::string& mid,
245       const std::string& transport_name,
246       cricket::VideoMediaInfo initial_stats = cricket::VideoMediaInfo()) {
247     auto video_media_channel =
248         std::make_unique<FakeVideoMediaChannelForStats>(network_thread_);
249     auto video_media_channel_ptr = video_media_channel.get();
250     auto video_channel = std::make_unique<VideoChannelForTesting>(
251         worker_thread_, network_thread_, signaling_thread_,
252         std::move(video_media_channel), mid, kDefaultSrtpRequired,
253         webrtc::CryptoOptions(), context_->ssrc_generator(), transport_name);
254     auto transceiver =
255         GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO)
256             ->internal();
257     if (transceiver->channel()) {
258       // This transceiver already has a channel, create a new one.
259       transceiver =
260           CreateTransceiverOfType(cricket::MEDIA_TYPE_VIDEO)->internal();
261     }
262     RTC_DCHECK(!transceiver->channel());
263     transceiver->SetChannel(std::move(video_channel),
264                             [](const std::string&) { return nullptr; });
265     video_media_channel_ptr->SetStats(initial_stats);
266     return video_media_channel_ptr;
267   }
268 
AddSctpDataChannel(const std::string & label)269   void AddSctpDataChannel(const std::string& label) {
270     AddSctpDataChannel(label, InternalDataChannelInit());
271   }
272 
AddSctpDataChannel(const std::string & label,const InternalDataChannelInit & init)273   void AddSctpDataChannel(const std::string& label,
274                           const InternalDataChannelInit& init) {
275     // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
276     AddSctpDataChannel(SctpDataChannel::Create(&data_channel_controller_, label,
277                                                init, rtc::Thread::Current(),
278                                                rtc::Thread::Current()));
279   }
280 
AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel)281   void AddSctpDataChannel(rtc::scoped_refptr<SctpDataChannel> data_channel) {
282     sctp_data_channels_.push_back(data_channel);
283   }
284 
SetTransportStats(const std::string & transport_name,const cricket::TransportChannelStats & channel_stats)285   void SetTransportStats(const std::string& transport_name,
286                          const cricket::TransportChannelStats& channel_stats) {
287     SetTransportStats(
288         transport_name,
289         std::vector<cricket::TransportChannelStats>{channel_stats});
290   }
291 
SetTransportStats(const std::string & transport_name,const std::vector<cricket::TransportChannelStats> & channel_stats_list)292   void SetTransportStats(
293       const std::string& transport_name,
294       const std::vector<cricket::TransportChannelStats>& channel_stats_list) {
295     cricket::TransportStats transport_stats;
296     transport_stats.transport_name = transport_name;
297     transport_stats.channel_stats = channel_stats_list;
298     transport_stats_by_name_[transport_name] = transport_stats;
299   }
300 
SetCallStats(const Call::Stats & call_stats)301   void SetCallStats(const Call::Stats& call_stats) { call_stats_ = call_stats; }
302 
SetLocalCertificate(const std::string & transport_name,rtc::scoped_refptr<rtc::RTCCertificate> certificate)303   void SetLocalCertificate(
304       const std::string& transport_name,
305       rtc::scoped_refptr<rtc::RTCCertificate> certificate) {
306     local_certificates_by_transport_[transport_name] = certificate;
307   }
308 
SetRemoteCertChain(const std::string & transport_name,std::unique_ptr<rtc::SSLCertChain> chain)309   void SetRemoteCertChain(const std::string& transport_name,
310                           std::unique_ptr<rtc::SSLCertChain> chain) {
311     remote_cert_chains_by_transport_[transport_name] = std::move(chain);
312   }
313 
314   // PeerConnectionInterface overrides.
315 
local_streams()316   rtc::scoped_refptr<StreamCollectionInterface> local_streams() override {
317     return local_streams_;
318   }
319 
remote_streams()320   rtc::scoped_refptr<StreamCollectionInterface> remote_streams() override {
321     return remote_streams_;
322   }
323 
GetSenders()324   std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
325       const override {
326     std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders;
327     for (auto transceiver : transceivers_) {
328       for (auto sender : transceiver->internal()->senders()) {
329         senders.push_back(sender);
330       }
331     }
332     return senders;
333   }
334 
GetReceivers()335   std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
336       const override {
337     std::vector<rtc::scoped_refptr<RtpReceiverInterface>> receivers;
338     for (auto transceiver : transceivers_) {
339       for (auto receiver : transceiver->internal()->receivers()) {
340         receivers.push_back(receiver);
341       }
342     }
343     return receivers;
344   }
345 
346   // PeerConnectionInternal overrides.
347 
network_thread()348   rtc::Thread* network_thread() const override { return network_thread_; }
349 
worker_thread()350   rtc::Thread* worker_thread() const override { return worker_thread_; }
351 
signaling_thread()352   rtc::Thread* signaling_thread() const override { return signaling_thread_; }
353 
354   std::vector<
355       rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
GetTransceiversInternal()356   GetTransceiversInternal() const override {
357     return transceivers_;
358   }
359 
GetDataChannelStats()360   std::vector<DataChannelStats> GetDataChannelStats() const override {
361     RTC_DCHECK_RUN_ON(signaling_thread());
362     std::vector<DataChannelStats> stats;
363     for (const auto& channel : sctp_data_channels_)
364       stats.push_back(channel->GetStats());
365     return stats;
366   }
367 
GetPooledCandidateStats()368   cricket::CandidateStatsList GetPooledCandidateStats() const override {
369     return {};
370   }
371 
GetTransportStatsByNames(const std::set<std::string> & transport_names)372   std::map<std::string, cricket::TransportStats> GetTransportStatsByNames(
373       const std::set<std::string>& transport_names) override {
374     RTC_DCHECK_RUN_ON(network_thread_);
375     std::map<std::string, cricket::TransportStats> transport_stats_by_name;
376     for (const std::string& transport_name : transport_names) {
377       transport_stats_by_name[transport_name] =
378           GetTransportStatsByName(transport_name);
379     }
380     return transport_stats_by_name;
381   }
382 
GetCallStats()383   Call::Stats GetCallStats() override { return call_stats_; }
384 
GetLocalCertificate(const std::string & transport_name,rtc::scoped_refptr<rtc::RTCCertificate> * certificate)385   bool GetLocalCertificate(
386       const std::string& transport_name,
387       rtc::scoped_refptr<rtc::RTCCertificate>* certificate) override {
388     auto it = local_certificates_by_transport_.find(transport_name);
389     if (it != local_certificates_by_transport_.end()) {
390       *certificate = it->second;
391       return true;
392     } else {
393       return false;
394     }
395   }
396 
GetRemoteSSLCertChain(const std::string & transport_name)397   std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain(
398       const std::string& transport_name) override {
399     auto it = remote_cert_chains_by_transport_.find(transport_name);
400     if (it != remote_cert_chains_by_transport_.end()) {
401       return it->second->Clone();
402     } else {
403       return nullptr;
404     }
405   }
406 
407  private:
GetTransportStatsByName(const std::string & transport_name)408   cricket::TransportStats GetTransportStatsByName(
409       const std::string& transport_name) {
410     auto it = transport_stats_by_name_.find(transport_name);
411     if (it != transport_stats_by_name_.end()) {
412       // If specific transport stats have been specified, return those.
413       return it->second;
414     }
415     // Otherwise, generate some dummy stats.
416     cricket::TransportChannelStats channel_stats;
417     channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
418     cricket::TransportStats transport_stats;
419     transport_stats.transport_name = transport_name;
420     transport_stats.channel_stats.push_back(channel_stats);
421     return transport_stats;
422   }
423 
424   rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type)425   GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type) {
426     for (auto transceiver : transceivers_) {
427       if (transceiver->internal()->media_type() == media_type) {
428         return transceiver;
429       }
430     }
431     return CreateTransceiverOfType(media_type);
432   }
433 
434   rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
CreateTransceiverOfType(cricket::MediaType media_type)435   CreateTransceiverOfType(cricket::MediaType media_type) {
436     auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
437         signaling_thread_,
438         rtc::make_ref_counted<RtpTransceiver>(media_type, context_.get()));
439     transceivers_.push_back(transceiver);
440     return transceiver;
441   }
442 
443   rtc::Thread* const network_thread_;
444   rtc::Thread* const worker_thread_;
445   rtc::Thread* const signaling_thread_;
446 
447   PeerConnectionFactoryDependencies dependencies_;
448   rtc::scoped_refptr<ConnectionContext> context_;
449 
450   rtc::scoped_refptr<StreamCollection> local_streams_;
451   rtc::scoped_refptr<StreamCollection> remote_streams_;
452 
453   std::vector<
454       rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
455       transceivers_;
456 
457   FakeDataChannelController data_channel_controller_;
458 
459   std::vector<rtc::scoped_refptr<SctpDataChannel>> sctp_data_channels_;
460 
461   std::map<std::string, cricket::TransportStats> transport_stats_by_name_;
462 
463   Call::Stats call_stats_;
464 
465   std::map<std::string, rtc::scoped_refptr<rtc::RTCCertificate>>
466       local_certificates_by_transport_;
467   std::map<std::string, std::unique_ptr<rtc::SSLCertChain>>
468       remote_cert_chains_by_transport_;
469 };
470 
471 }  // namespace webrtc
472 
473 #endif  // PC_TEST_FAKE_PEER_CONNECTION_FOR_STATS_H_
474