/* * Copyright 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef PC_TEST_FAKEPEERCONNECTIONFORSTATS_H_ #define PC_TEST_FAKEPEERCONNECTIONFORSTATS_H_ #include #include #include #include #include #include #include "media/base/fakemediaengine.h" #include "pc/streamcollection.h" #include "pc/test/fakedatachannelprovider.h" #include "pc/test/fakepeerconnectionbase.h" namespace webrtc { // Fake VoiceMediaChannel where the result of GetStats can be configured. class FakeVoiceMediaChannelForStats : public cricket::FakeVoiceMediaChannel { public: FakeVoiceMediaChannelForStats() : cricket::FakeVoiceMediaChannel(nullptr, cricket::AudioOptions()) {} void SetStats(const cricket::VoiceMediaInfo& voice_info) { stats_ = voice_info; } // VoiceMediaChannel overrides. bool GetStats(cricket::VoiceMediaInfo* info) override { if (stats_) { *info = *stats_; return true; } return false; } private: rtc::Optional stats_; }; // Fake VideoMediaChannel where the result of GetStats can be configured. class FakeVideoMediaChannelForStats : public cricket::FakeVideoMediaChannel { public: FakeVideoMediaChannelForStats() : cricket::FakeVideoMediaChannel(nullptr, cricket::VideoOptions()) {} void SetStats(const cricket::VideoMediaInfo& video_info) { stats_ = video_info; } // VideoMediaChannel overrides. bool GetStats(cricket::VideoMediaInfo* info) override { if (stats_) { *info = *stats_; return true; } return false; } private: rtc::Optional stats_; }; constexpr bool kDefaultRtcpMuxRequired = true; constexpr bool kDefaultSrtpRequired = true; // This class is intended to be fed into the StatsCollector and // RTCStatsCollector so that the stats functionality can be unit tested. // Individual tests can configure this fake as needed to simulate scenarios // under which to test the stats collectors. class FakePeerConnectionForStats : public FakePeerConnectionBase { public: // TODO(steveanton): Add support for specifying separate threads to test // multi-threading correctness. FakePeerConnectionForStats() : network_thread_(rtc::Thread::Current()), worker_thread_(rtc::Thread::Current()), signaling_thread_(rtc::Thread::Current()), local_streams_(StreamCollection::Create()), remote_streams_(StreamCollection::Create()) {} rtc::scoped_refptr mutable_local_streams() { return local_streams_; } rtc::scoped_refptr mutable_remote_streams() { return remote_streams_; } void AddSender(rtc::scoped_refptr sender) { // TODO(steveanton): Switch tests to use RtpTransceivers directly. auto sender_proxy = RtpSenderProxyWithInternal::Create( signaling_thread_, sender); GetOrCreateFirstTransceiverOfType(sender->media_type()) ->internal() ->AddSender(sender_proxy); } void AddReceiver(rtc::scoped_refptr receiver) { // TODO(steveanton): Switch tests to use RtpTransceivers directly. auto receiver_proxy = RtpReceiverProxyWithInternal::Create( signaling_thread_, receiver); GetOrCreateFirstTransceiverOfType(receiver->media_type()) ->internal() ->AddReceiver(receiver_proxy); } FakeVoiceMediaChannelForStats* AddVoiceChannel( const std::string& mid, const std::string& transport_name) { RTC_DCHECK(!voice_channel_); auto voice_media_channel = rtc::MakeUnique(); auto* voice_media_channel_ptr = voice_media_channel.get(); voice_channel_ = rtc::MakeUnique( worker_thread_, network_thread_, signaling_thread_, nullptr, std::move(voice_media_channel), mid, kDefaultSrtpRequired, rtc::CryptoOptions()); voice_channel_->set_transport_name_for_testing(transport_name); GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_AUDIO) ->internal() ->SetChannel(voice_channel_.get()); return voice_media_channel_ptr; } FakeVideoMediaChannelForStats* AddVideoChannel( const std::string& mid, const std::string& transport_name) { RTC_DCHECK(!video_channel_); auto video_media_channel = rtc::MakeUnique(); auto video_media_channel_ptr = video_media_channel.get(); video_channel_ = rtc::MakeUnique( worker_thread_, network_thread_, signaling_thread_, std::move(video_media_channel), mid, kDefaultSrtpRequired, rtc::CryptoOptions()); video_channel_->set_transport_name_for_testing(transport_name); GetOrCreateFirstTransceiverOfType(cricket::MEDIA_TYPE_VIDEO) ->internal() ->SetChannel(video_channel_.get()); return video_media_channel_ptr; } void AddLocalTrack(uint32_t ssrc, const std::string& track_id) { local_track_id_by_ssrc_[ssrc] = track_id; } void AddRemoteTrack(uint32_t ssrc, const std::string& track_id) { remote_track_id_by_ssrc_[ssrc] = track_id; } void AddSctpDataChannel(const std::string& label) { AddSctpDataChannel(label, InternalDataChannelInit()); } void AddSctpDataChannel(const std::string& label, const InternalDataChannelInit& init) { AddSctpDataChannel(DataChannel::Create(&data_channel_provider_, cricket::DCT_SCTP, label, init)); } void AddSctpDataChannel(rtc::scoped_refptr data_channel) { sctp_data_channels_.push_back(data_channel); } void SetTransportStats(const std::string& transport_name, const cricket::TransportChannelStats& channel_stats) { SetTransportStats( transport_name, std::vector{channel_stats}); } void SetTransportStats( const std::string& transport_name, const std::vector& channel_stats_list) { cricket::TransportStats transport_stats; transport_stats.transport_name = transport_name; transport_stats.channel_stats = channel_stats_list; transport_stats_by_name_[transport_name] = transport_stats; } void SetCallStats(const Call::Stats& call_stats) { call_stats_ = call_stats; } void SetLocalCertificate( const std::string& transport_name, rtc::scoped_refptr certificate) { local_certificates_by_transport_[transport_name] = certificate; } void SetRemoteCertChain(const std::string& transport_name, std::unique_ptr chain) { remote_cert_chains_by_transport_[transport_name] = std::move(chain); } // PeerConnectionInterface overrides. rtc::scoped_refptr local_streams() override { return local_streams_; } rtc::scoped_refptr remote_streams() override { return remote_streams_; } std::vector> GetSenders() const override { std::vector> senders; for (auto transceiver : transceivers_) { for (auto sender : transceiver->internal()->senders()) { senders.push_back(sender); } } return senders; } std::vector> GetReceivers() const override { std::vector> receivers; for (auto transceiver : transceivers_) { for (auto receiver : transceiver->internal()->receivers()) { receivers.push_back(receiver); } } return receivers; } // PeerConnectionInternal overrides. rtc::Thread* network_thread() const override { return network_thread_; } rtc::Thread* worker_thread() const override { return worker_thread_; } rtc::Thread* signaling_thread() const override { return signaling_thread_; } std::vector< rtc::scoped_refptr>> GetTransceiversInternal() const override { return transceivers_; } bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id) override { auto it = local_track_id_by_ssrc_.find(ssrc); if (it != local_track_id_by_ssrc_.end()) { *track_id = it->second; return true; } else { return false; } } bool GetRemoteTrackIdBySsrc(uint32_t ssrc, std::string* track_id) override { auto it = remote_track_id_by_ssrc_.find(ssrc); if (it != remote_track_id_by_ssrc_.end()) { *track_id = it->second; return true; } else { return false; } } std::vector> sctp_data_channels() const override { return sctp_data_channels_; } cricket::CandidateStatsList GetPooledCandidateStats() const override { return {}; } std::map GetTransportNamesByMid() const override { std::map transport_names_by_mid; if (voice_channel_) { transport_names_by_mid[voice_channel_->content_name()] = voice_channel_->transport_name(); } if (video_channel_) { transport_names_by_mid[video_channel_->content_name()] = video_channel_->transport_name(); } return transport_names_by_mid; } std::map GetTransportStatsByNames( const std::set& transport_names) override { std::map transport_stats_by_name; for (const std::string& transport_name : transport_names) { transport_stats_by_name[transport_name] = GetTransportStatsByName(transport_name); } return transport_stats_by_name; } Call::Stats GetCallStats() override { return call_stats_; } bool GetLocalCertificate( const std::string& transport_name, rtc::scoped_refptr* certificate) override { auto it = local_certificates_by_transport_.find(transport_name); if (it != local_certificates_by_transport_.end()) { *certificate = it->second; return true; } else { return false; } } std::unique_ptr GetRemoteSSLCertChain( const std::string& transport_name) override { auto it = remote_cert_chains_by_transport_.find(transport_name); if (it != remote_cert_chains_by_transport_.end()) { return it->second->UniqueCopy(); } else { return nullptr; } } private: cricket::TransportStats GetTransportStatsByName( const std::string& transport_name) { auto it = transport_stats_by_name_.find(transport_name); if (it != transport_stats_by_name_.end()) { // If specific transport stats have been specified, return those. return it->second; } // Otherwise, generate some dummy stats. cricket::TransportChannelStats channel_stats; channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; cricket::TransportStats transport_stats; transport_stats.transport_name = transport_name; transport_stats.channel_stats.push_back(channel_stats); return transport_stats; } rtc::scoped_refptr> GetOrCreateFirstTransceiverOfType(cricket::MediaType media_type) { for (auto transceiver : transceivers_) { if (transceiver->internal()->media_type() == media_type) { return transceiver; } } auto transceiver = RtpTransceiverProxyWithInternal::Create( signaling_thread_, new RtpTransceiver(media_type)); transceivers_.push_back(transceiver); return transceiver; } rtc::Thread* const network_thread_; rtc::Thread* const worker_thread_; rtc::Thread* const signaling_thread_; rtc::scoped_refptr local_streams_; rtc::scoped_refptr remote_streams_; std::vector< rtc::scoped_refptr>> transceivers_; FakeDataChannelProvider data_channel_provider_; std::unique_ptr voice_channel_; std::unique_ptr video_channel_; std::map local_track_id_by_ssrc_; std::map remote_track_id_by_ssrc_; std::vector> sctp_data_channels_; std::map transport_stats_by_name_; Call::Stats call_stats_; std::map> local_certificates_by_transport_; std::map> remote_cert_chains_by_transport_; }; } // namespace webrtc #endif // PC_TEST_FAKEPEERCONNECTIONFORSTATS_H_