From 3871f6f9d417f10d971b8332c82acc4924eec221 Mon Sep 17 00:00:00 2001 From: Steve Anton Date: Fri, 26 Jan 2018 10:25:53 -0800 Subject: [PATCH] Rewrite StatsCollector tests to use a fake PeerConnection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes use of the MockPeerConnection and replaces it with a fake implementation of PeerConnection tailored to the needs of StatsCollector and (soon) RTCStatsCollector. The stats collector tests really care about the PeerConnection only so much as to set up scenarios to test the StatsCollector with. Since each scenario (e.g., adding a track) affects the results of multiple methods (e.g., voice_channel and SessionStats), the tests were needing to manually configure these dependent operations which was tedious, error prone and difficult to change. The new fake lets the tests express the scenario more concisely (e.g., AddVoiceChannel) while filling in all the affected methods on the PeerConnection automatically. Furthermore, this can be expanded to use with the RTCStatsCollector and to cover more scenarios in the future. Bug: webrtc:8764 Change-Id: I195074174684256543f7cdc27c3834e5ff0b4702 Reviewed-on: https://webrtc-review.googlesource.com/43521 Commit-Queue: Steve Anton Reviewed-by: Henrik Boström Reviewed-by: Peter Thatcher Reviewed-by: Taylor Brandstetter Cr-Commit-Position: refs/heads/master@{#21778} --- pc/BUILD.gn | 1 + pc/statscollector_unittest.cc | 1364 +++++++++----------------- pc/test/fakepeerconnectionforstats.h | 303 ++++++ 3 files changed, 764 insertions(+), 904 deletions(-) create mode 100644 pc/test/fakepeerconnectionforstats.h diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 588a88aab9..a65b60380e 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -330,6 +330,7 @@ if (rtc_include_tests) { "test/fakeaudiocapturemodule.h", "test/fakedatachannelprovider.h", "test/fakepeerconnectionbase.h", + "test/fakepeerconnectionforstats.h", "test/fakeperiodicvideocapturer.h", "test/fakertccertificategenerator.h", "test/fakesctptransport.h", diff --git a/pc/statscollector_unittest.cc b/pc/statscollector_unittest.cc index eb2081d7d7..6e980e566d 100644 --- a/pc/statscollector_unittest.cc +++ b/pc/statscollector_unittest.cc @@ -16,46 +16,24 @@ #include "pc/statscollector.h" -#include "api/mediastreaminterface.h" -#include "media/base/fakemediaengine.h" -#include "media/base/test/mock_mediachannel.h" -#include "pc/channelmanager.h" #include "pc/mediastream.h" #include "pc/mediastreamtrack.h" -#include "pc/peerconnection.h" -#include "pc/peerconnectionfactory.h" -#include "pc/test/fakedatachannelprovider.h" +#include "pc/test/fakepeerconnectionforstats.h" #include "pc/test/fakevideotracksource.h" -#include "pc/test/mock_peerconnection.h" #include "pc/videotrack.h" #include "rtc_base/base64.h" #include "rtc_base/fakesslidentity.h" -#include "rtc_base/gunit.h" -#include "rtc_base/stringencode.h" -#include "test/gmock.h" #include "test/gtest.h" -using testing::_; -using testing::DoAll; -using testing::Field; -using testing::Invoke; -using testing::Return; -using testing::ReturnNull; -using testing::SetArgPointee; -using webrtc::PeerConnectionInterface; -using webrtc::StatsReport; -using webrtc::StatsReports; - -namespace { -const bool kDefaultRtcpMuxRequired = true; -const bool kDefaultSrtpRequired = true; -} - -namespace cricket { - -class ChannelManager; - -} // namespace cricket +using cricket::ConnectionInfo; +using cricket::SsrcReceiverInfo; +using cricket::TransportChannelStats; +using cricket::VideoMediaInfo; +using cricket::VideoReceiverInfo; +using cricket::VideoSenderInfo; +using cricket::VoiceMediaInfo; +using cricket::VoiceReceiverInfo; +using cricket::VoiceSenderInfo; namespace webrtc { @@ -72,7 +50,7 @@ const char kLocalTrackId[] = "local_track_id"; const char kRemoteTrackId[] = "remote_track_id"; const uint32_t kSsrcOfTrack = 1234; -class FakeAudioProcessor : public webrtc::AudioProcessorInterface { +class FakeAudioProcessor : public AudioProcessorInterface { public: FakeAudioProcessor() {} ~FakeAudioProcessor() {} @@ -100,22 +78,20 @@ class FakeAudioProcessor : public webrtc::AudioProcessorInterface { } }; -class FakeAudioTrack - : public webrtc::MediaStreamTrack { +class FakeAudioTrack : public MediaStreamTrack { public: explicit FakeAudioTrack(const std::string& id) - : webrtc::MediaStreamTrack(id), + : MediaStreamTrack(id), processor_(new rtc::RefCountedObject()) {} std::string kind() const override { return "audio"; } - webrtc::AudioSourceInterface* GetSource() const override { return NULL; } - void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} - void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} + AudioSourceInterface* GetSource() const override { return NULL; } + void AddSink(AudioTrackSinkInterface* sink) override {} + void RemoveSink(AudioTrackSinkInterface* sink) override {} bool GetSignalLevel(int* level) override { *level = 1; return true; } - rtc::scoped_refptr GetAudioProcessor() - override { + rtc::scoped_refptr GetAudioProcessor() override { return processor_; } @@ -125,7 +101,7 @@ class FakeAudioTrack // This fake audio processor is used to verify that the undesired initial values // (-1) will be filtered out. -class FakeAudioProcessorWithInitValue : public webrtc::AudioProcessorInterface { +class FakeAudioProcessorWithInitValue : public AudioProcessorInterface { public: FakeAudioProcessorWithInitValue() {} ~FakeAudioProcessorWithInitValue() {} @@ -148,22 +124,21 @@ class FakeAudioProcessorWithInitValue : public webrtc::AudioProcessorInterface { }; class FakeAudioTrackWithInitValue - : public webrtc::MediaStreamTrack { + : public MediaStreamTrack { public: explicit FakeAudioTrackWithInitValue(const std::string& id) - : webrtc::MediaStreamTrack(id), + : MediaStreamTrack(id), processor_( new rtc::RefCountedObject()) {} std::string kind() const override { return "audio"; } - webrtc::AudioSourceInterface* GetSource() const override { return NULL; } - void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} - void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} + AudioSourceInterface* GetSource() const override { return NULL; } + void AddSink(AudioTrackSinkInterface* sink) override {} + void RemoveSink(AudioTrackSinkInterface* sink) override {} bool GetSignalLevel(int* level) override { *level = 1; return true; } - rtc::scoped_refptr GetAudioProcessor() - override { + rtc::scoped_refptr GetAudioProcessor() override { return processor_; } @@ -556,9 +531,8 @@ void UpdateVoiceSenderInfoFromAudioTrack( cricket::VoiceSenderInfo* voice_sender_info, bool has_remote_tracks) { audio_track->GetSignalLevel(&voice_sender_info->audio_level); - webrtc::AudioProcessorInterface::AudioProcessorStatistics - audio_processor_stats = - audio_track->GetAudioProcessor()->GetStats(has_remote_tracks); + AudioProcessorInterface::AudioProcessorStatistics audio_processor_stats = + audio_track->GetAudioProcessor()->GetStats(has_remote_tracks); voice_sender_info->typing_noise_detected = audio_processor_stats.typing_noise_detected; voice_sender_info->apm_statistics = audio_processor_stats.apm_statistics; @@ -585,9 +559,9 @@ void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) { voice_receiver_info->secondary_discarded_rate = 126; } -class StatsCollectorForTest : public webrtc::StatsCollector { +class StatsCollectorForTest : public StatsCollector { public: - explicit StatsCollectorForTest(PeerConnection* pc) + explicit StatsCollectorForTest(PeerConnectionInternal* pc) : StatsCollector(pc), time_now_(19477) {} double GetTimeNow() override { @@ -600,104 +574,27 @@ class StatsCollectorForTest : public webrtc::StatsCollector { class StatsCollectorTest : public testing::Test { protected: - StatsCollectorTest() - : worker_thread_(rtc::Thread::Current()), - network_thread_(rtc::Thread::Current()), - media_engine_(new cricket::FakeMediaEngine()), - pc_factory_(new FakePeerConnectionFactory( - std::unique_ptr(media_engine_))), - pc_(pc_factory_) { - // By default, we ignore session GetStats calls. - EXPECT_CALL(pc_, GetSessionStats(_)).WillRepeatedly(ReturnNull()); - // Add default returns for mock classes. - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(pc_, sctp_data_channels()) - .WillRepeatedly(Return(data_channels_)); - EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( - std::vector>())); - EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( - std::vector>())); - // Boring calls - EXPECT_CALL(pc_, GetCallStats()).WillRepeatedly(Return(Call::Stats())); + rtc::scoped_refptr CreatePeerConnection() { + return new rtc::RefCountedObject(); } - ~StatsCollectorTest() {} - - // This creates a standard setup with a transport called "trspname" - // having one transport channel - // and the specified virtual connection name. - void InitSessionStats(cricket::BaseChannel* channel) { - const std::string kTransportName("trspname"); - cricket::TransportStats transport_stats; - cricket::TransportChannelStats channel_stats; - channel_stats.component = 1; - transport_stats.transport_name = kTransportName; - transport_stats.channel_stats.push_back(channel_stats); - - session_stats_.transport_stats[kTransportName] = transport_stats; - channel->set_transport_name_for_testing(kTransportName); + std::unique_ptr CreateStatsCollector( + PeerConnectionInternal* pc) { + return rtc::MakeUnique(pc); } - void AddDataChannel(cricket::DataChannelType type, - const std::string& label, - int id) { - InternalDataChannelInit config; - config.id = id; - - data_channels_.push_back(DataChannel::Create( - &data_channel_provider_, cricket::DCT_SCTP, label, config)); - EXPECT_CALL(pc_, sctp_data_channels()) - .WillRepeatedly(Return(data_channels_)); - } - - StatsReport* AddCandidateReport(StatsCollector* collector, - const cricket::Candidate& candidate, - bool local) { - return collector->AddCandidateReport(candidate, local); - } - - void SetupAndVerifyAudioTrackStats( - FakeAudioTrack* audio_track, - webrtc::MediaStream* stream, - webrtc::StatsCollector* stats, - cricket::VoiceChannel* voice_channel, - MockVoiceMediaChannel* media_channel, - cricket::VoiceSenderInfo* voice_sender_info, - cricket::VoiceReceiverInfo* voice_receiver_info, - cricket::VoiceMediaInfo* stats_read, - StatsReports* reports) { - // A track can't have both sender report and recv report at the same time - // for now, this might change in the future though. - EXPECT_TRUE((voice_sender_info == NULL) ^ (voice_receiver_info == NULL)); - - // Instruct the session to return stats containing the transport channel. - InitSessionStats(voice_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - // Constructs an ssrc stats update. - if (voice_sender_info) - stats_read->senders.push_back(*voice_sender_info); - if (voice_receiver_info) - stats_read->receivers.push_back(*voice_receiver_info); - - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(Return(voice_channel)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(*stats_read), Return(true))); - + void VerifyAudioTrackStats(FakeAudioTrack* audio_track, + StatsCollectorForTest* stats, + const VoiceMediaInfo& voice_info, + StatsReports* reports) { stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats->ClearUpdateStatsCacheForTest(); - stats->GetStats(NULL, reports); + stats->GetStats(nullptr, reports); // Verify the existence of the track report. const StatsReport* report = FindNthReportByType( *reports, StatsReport::kStatsReportTypeSsrc, 1); - EXPECT_FALSE(report == NULL); + ASSERT_TRUE(report); EXPECT_EQ(stats->GetTimeNow(), report->timestamp()); std::string track_id = ExtractSsrcStatsValue( *reports, StatsReport::kStatsValueNameTrackId); @@ -711,13 +608,11 @@ class StatsCollectorTest : public testing::Test { EXPECT_EQ("audio", media_type); // Verifies the values in the track report. - if (voice_sender_info) { - UpdateVoiceSenderInfoFromAudioTrack(audio_track, voice_sender_info, - stats_read->receivers.size() > 0); - VerifyVoiceSenderInfoReport(report, *voice_sender_info); + if (!voice_info.senders.empty()) { + VerifyVoiceSenderInfoReport(report, voice_info.senders[0]); } - if (voice_receiver_info) { - VerifyVoiceReceiverInfoReport(report, *voice_receiver_info); + if (!voice_info.receivers.empty()) { + VerifyVoiceReceiverInfoReport(report, voice_info.receivers[0]); } // Verify we get the same result by passing a track to GetStats(). @@ -725,9 +620,7 @@ class StatsCollectorTest : public testing::Test { stats->GetStats(audio_track, &track_reports); const StatsReport* track_report = FindNthReportByType( track_reports, StatsReport::kStatsReportTypeSsrc, 1); - EXPECT_TRUE(track_report); - if (!track_report) - return; + ASSERT_TRUE(track_report); EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); track_id = ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameTrackId); @@ -735,10 +628,12 @@ class StatsCollectorTest : public testing::Test { ssrc_id = ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameSsrc); EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id); - if (voice_sender_info) - VerifyVoiceSenderInfoReport(track_report, *voice_sender_info); - if (voice_receiver_info) - VerifyVoiceReceiverInfoReport(track_report, *voice_receiver_info); + if (!voice_info.senders.empty()) { + VerifyVoiceSenderInfoReport(track_report, voice_info.senders[0]); + } + if (!voice_info.receivers.empty()) { + VerifyVoiceReceiverInfoReport(track_report, voice_info.receivers[0]); + } } void TestCertificateReports( @@ -746,49 +641,36 @@ class StatsCollectorTest : public testing::Test { const std::vector& local_ders, std::unique_ptr remote_cert, const std::vector& remote_ders) { - StatsCollectorForTest stats(&pc_); + const std::string kTransportName = "transport"; - StatsReports reports; // returned values. + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); + + pc->AddVoiceChannel("audio", kTransportName, VoiceMediaInfo()); // Fake stats to process. - cricket::TransportChannelStats channel_stats; + TransportChannelStats channel_stats; channel_stats.component = 1; channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; channel_stats.ssl_cipher_suite = internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; - - cricket::TransportStats transport_stats; - transport_stats.transport_name = "audio"; - transport_stats.channel_stats.push_back(channel_stats); - - SessionStats session_stats; - session_stats.transport_stats[transport_stats.transport_name] = - transport_stats; + pc->SetTransportStats(kTransportName, channel_stats); // Fake certificate to report rtc::scoped_refptr local_certificate( - rtc::RTCCertificate::Create(std::unique_ptr( - new rtc::FakeSSLIdentity(local_cert)))); + rtc::RTCCertificate::Create( + rtc::MakeUnique(local_cert))); + pc->SetLocalCertificate(kTransportName, local_certificate); + pc->SetRemoteCertificate(kTransportName, std::move(remote_cert)); - // Configure MockWebRtcSession - EXPECT_CALL(pc_, GetLocalCertificate(transport_stats.transport_name, _)) - .WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true))); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer( - transport_stats.transport_name)) - .WillOnce(Return(remote_cert.release())); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillOnce(Invoke([&session_stats](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats)); - })); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - - stats.GetStats(NULL, &reports); + StatsReports reports; + stats->GetStats(nullptr, &reports); const StatsReport* channel_report = FindNthReportByType( reports, StatsReport::kStatsReportTypeComponent, 1); - EXPECT_TRUE(channel_report != NULL); + EXPECT_TRUE(channel_report); // Check local certificate chain. std::string local_certificate_id = ExtractStatsValue( @@ -829,17 +711,6 @@ class StatsCollectorTest : public testing::Test { EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::SRTP_AES128_CM_SHA1_80), srtp_crypto_suite); } - - webrtc::RtcEventLogNullImpl event_log_; - rtc::Thread* const worker_thread_; - rtc::Thread* const network_thread_; - // |media_engine_| is actually owned by |pc_factory_|. - cricket::FakeMediaEngine* media_engine_; - rtc::scoped_refptr pc_factory_; - MockPeerConnection pc_; - FakeDataChannelProvider data_channel_provider_; - SessionStats session_stats_; - std::vector> data_channels_; }; class StatsCollectorTrackTest : public StatsCollectorTest, @@ -848,90 +719,83 @@ class StatsCollectorTrackTest : public StatsCollectorTest, // Adds a outgoing video track with a given SSRC into the stats. // If GetParam() returns true, the track is also inserted into the local // stream, which is created if necessary. - void AddOutgoingVideoTrackStats(StatsCollectorForTest* stats) { - track_ = webrtc::VideoTrack::Create(kLocalTrackId, - webrtc::FakeVideoTrackSource::Create(), - rtc::Thread::Current()); + void AddOutgoingVideoTrack(FakePeerConnectionForStats* pc, + StatsCollectorForTest* stats) { + track_ = VideoTrack::Create(kLocalTrackId, FakeVideoTrackSource::Create(), + rtc::Thread::Current()); if (GetParam()) { if (!stream_) - stream_ = webrtc::MediaStream::Create("streamlabel"); + stream_ = MediaStream::Create("streamlabel"); stream_->AddTrack(track_); stats->AddStream(stream_); } else { stats->AddTrack(track_); } - EXPECT_CALL(pc_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); + pc->AddLocalTrack(kSsrcOfTrack, kLocalTrackId); } // Adds a incoming video track with a given SSRC into the stats. - void AddIncomingVideoTrackStats(StatsCollectorForTest* stats) { - track_ = webrtc::VideoTrack::Create(kRemoteTrackId, - webrtc::FakeVideoTrackSource::Create(), - rtc::Thread::Current()); + void AddIncomingVideoTrack(FakePeerConnectionForStats* pc, + StatsCollectorForTest* stats) { + track_ = VideoTrack::Create(kRemoteTrackId, FakeVideoTrackSource::Create(), + rtc::Thread::Current()); if (GetParam()) { - stream_ = webrtc::MediaStream::Create("streamlabel"); + stream_ = MediaStream::Create("streamlabel"); stream_->AddTrack(track_); stats->AddStream(stream_); } else { stats->AddTrack(track_); } - EXPECT_CALL(pc_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); + pc->AddRemoteTrack(kSsrcOfTrack, kRemoteTrackId); } // Adds a outgoing audio track with a given SSRC into the stats, // and register it into the stats object. // If GetParam() returns true, the track is also inserted into the local // stream, which is created if necessary. - void AddOutgoingAudioTrackStats(StatsCollectorForTest* stats) { + void AddOutgoingAudioTrack(FakePeerConnectionForStats* pc, + StatsCollectorForTest* stats) { audio_track_ = new rtc::RefCountedObject(kLocalTrackId); if (GetParam()) { if (!stream_) - stream_ = webrtc::MediaStream::Create("streamlabel"); + stream_ = MediaStream::Create("streamlabel"); stream_->AddTrack(audio_track_); stats->AddStream(stream_); } else { stats->AddTrack(audio_track_); } - EXPECT_CALL(pc_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); + pc->AddLocalTrack(kSsrcOfTrack, kLocalTrackId); } // Adds a incoming audio track with a given SSRC into the stats. - void AddIncomingAudioTrackStats(StatsCollectorForTest* stats) { + void AddIncomingAudioTrack(FakePeerConnectionForStats* pc, + StatsCollectorForTest* stats) { audio_track_ = new rtc::RefCountedObject(kRemoteTrackId); if (GetParam()) { if (stream_ == NULL) - stream_ = webrtc::MediaStream::Create("streamlabel"); + stream_ = MediaStream::Create("streamlabel"); stream_->AddTrack(audio_track_); stats->AddStream(stream_); } else { stats->AddTrack(audio_track_); } - EXPECT_CALL(pc_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); + pc->AddRemoteTrack(kSsrcOfTrack, kRemoteTrackId); } - rtc::scoped_refptr stream_; - rtc::scoped_refptr track_; + rtc::scoped_refptr stream_; + rtc::scoped_refptr track_; rtc::scoped_refptr audio_track_; }; TEST_F(StatsCollectorTest, FilterOutNegativeDataChannelId) { - const std::string label = "hacks"; - // The data channel id is from the Config which is -1 initially. - const int id = -1; - const std::string state = DataChannelInterface::DataStateString( - DataChannelInterface::DataState::kConnecting); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - AddDataChannel(cricket::DCT_SCTP, label, id); - StatsCollectorForTest stats(&pc_); - - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + pc->AddSctpDataChannel("hacks"); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); const StatsReport* report = FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); @@ -943,37 +807,40 @@ TEST_F(StatsCollectorTest, FilterOutNegativeDataChannelId) { // Verify that ExtractDataInfo populates reports. TEST_F(StatsCollectorTest, ExtractDataInfo) { - const std::string label = "hacks"; - const int id = 31337; - const std::string state = DataChannelInterface::DataStateString( + const std::string kDataChannelLabel = "hacks"; + constexpr int kDataChannelId = 31337; + const std::string kConnectingString = DataChannelInterface::DataStateString( DataChannelInterface::DataState::kConnecting); - AddDataChannel(cricket::DCT_SCTP, label, id); - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + InternalDataChannelInit init; + init.id = kDataChannelId; + pc->AddSctpDataChannel(kDataChannelLabel, init); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); const StatsReport* report = FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); - StatsReport::Id reportId = StatsReport::NewTypedIntId( - StatsReport::kStatsReportTypeDataChannel, id); + StatsReport::Id report_id = StatsReport::NewTypedIntId( + StatsReport::kStatsReportTypeDataChannel, kDataChannelId); - EXPECT_TRUE(reportId->Equals(report->id())); + EXPECT_TRUE(report_id->Equals(report->id())); - EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); - EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, - reports, - StatsReport::kStatsValueNameLabel)); - EXPECT_EQ(rtc::ToString(id), + EXPECT_EQ(stats->GetTimeNow(), report->timestamp()); + EXPECT_EQ(kDataChannelLabel, + ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, + StatsReport::kStatsValueNameLabel)); + EXPECT_EQ(rtc::ToString(kDataChannelId), ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, StatsReport::kStatsValueNameDataChannelId)); - EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, - reports, - StatsReport::kStatsValueNameState)); + EXPECT_EQ(kConnectingString, + ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, + StatsReport::kStatsValueNameState)); EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, StatsReport::kStatsValueNameProtocol)); @@ -981,223 +848,166 @@ TEST_F(StatsCollectorTest, ExtractDataInfo) { // This test verifies that 64-bit counters are passed successfully. TEST_P(StatsCollectorTrackTest, BytesCounterHandles64Bits) { - StatsCollectorForTest stats(&pc_); - - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - StatsReports reports; // returned values. - cricket::VideoSenderInfo video_sender_info; - cricket::VideoMediaInfo stats_read; // The number of bytes must be larger than 0xFFFFFFFF for this test. - const int64_t kBytesSent = 12345678901234LL; - const std::string kBytesSentString("12345678901234"); + constexpr int64_t kBytesSent = 12345678901234LL; - AddOutgoingVideoTrackStats(&stats); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - // Construct a stats value to read. + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(1234); video_sender_info.bytes_sent = kBytesSent; - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), - Return(true))); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - std::string result = ExtractSsrcStatsValue(reports, - StatsReport::kStatsValueNameBytesSent); - EXPECT_EQ(kBytesSentString, result); + AddOutgoingVideoTrack(pc, stats.get()); + + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); + + EXPECT_EQ( + rtc::ToString(kBytesSent), + ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent)); } // Test that audio BWE information is reported via stats. TEST_P(StatsCollectorTrackTest, AudioBandwidthEstimationInfoIsReported) { - StatsCollectorForTest stats(&pc_); - - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel(worker_thread_, network_thread_, nullptr, - nullptr, rtc::WrapUnique(media_channel), - "audio", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); - - InitSessionStats(&voice_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr(new SessionStats(session_stats_)); - })); - - StatsReports reports; // returned values. - cricket::VoiceSenderInfo voice_sender_info; - cricket::VoiceMediaInfo stats_read; // Set up an SSRC just to test that we get both kinds of stats back: SSRC and // BWE. - const int64_t kBytesSent = 12345678901234LL; - const std::string kBytesSentString("12345678901234"); + constexpr int64_t kBytesSent = 12345678901234LL; + constexpr int kSendBandwidth = 1234567; + constexpr int kRecvBandwidth = 12345678; + constexpr int kPacerDelay = 123; - AddOutgoingAudioTrackStats(&stats); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - // Construct a stats value to read. + VoiceSenderInfo voice_sender_info; voice_sender_info.add_ssrc(1234); voice_sender_info.bytes_sent = kBytesSent; - stats_read.senders.push_back(voice_sender_info); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); + pc->AddVoiceChannel("audio", "transport", voice_info); - webrtc::Call::Stats call_stats; - const int kSendBandwidth = 1234567; - const int kRecvBandwidth = 12345678; - const int kPacerDelay = 123; + AddOutgoingAudioTrack(pc, stats.get()); + + Call::Stats call_stats; call_stats.send_bandwidth_bps = kSendBandwidth; call_stats.recv_bandwidth_bps = kRecvBandwidth; call_stats.pacer_delay_ms = kPacerDelay; - EXPECT_CALL(pc_, GetCallStats()).WillRepeatedly(Return(call_stats)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(Return(&voice_channel)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); + pc->SetCallStats(call_stats); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - std::string result = - ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent); - EXPECT_EQ(kBytesSentString, result); - result = ExtractBweStatsValue( - reports, StatsReport::kStatsValueNameAvailableSendBandwidth); - EXPECT_EQ(rtc::ToString(kSendBandwidth), result); - result = ExtractBweStatsValue( - reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth); - EXPECT_EQ(rtc::ToString(kRecvBandwidth), result); - result = - ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay); - EXPECT_EQ(rtc::ToString(kPacerDelay), result); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); + + EXPECT_EQ( + rtc::ToString(kBytesSent), + ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent)); + EXPECT_EQ(rtc::ToString(kSendBandwidth), + ExtractBweStatsValue( + reports, StatsReport::kStatsValueNameAvailableSendBandwidth)); + EXPECT_EQ( + rtc::ToString(kRecvBandwidth), + ExtractBweStatsValue( + reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth)); + EXPECT_EQ( + rtc::ToString(kPacerDelay), + ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay)); } // Test that video BWE information is reported via stats. TEST_P(StatsCollectorTrackTest, VideoBandwidthEstimationInfoIsReported) { - StatsCollectorForTest stats(&pc_); - - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - StatsReports reports; // returned values. - cricket::VideoSenderInfo video_sender_info; - cricket::VideoMediaInfo stats_read; // Set up an SSRC just to test that we get both kinds of stats back: SSRC and // BWE. - const int64_t kBytesSent = 12345678901234LL; - const std::string kBytesSentString("12345678901234"); + constexpr int64_t kBytesSent = 12345678901234LL; + constexpr int kSendBandwidth = 1234567; + constexpr int kRecvBandwidth = 12345678; + constexpr int kPacerDelay = 123; - AddOutgoingVideoTrackStats(&stats); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - // Construct a stats value to read. + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(1234); video_sender_info.bytes_sent = kBytesSent; - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); - webrtc::Call::Stats call_stats; - const int kSendBandwidth = 1234567; - const int kRecvBandwidth = 12345678; - const int kPacerDelay = 123; + AddOutgoingVideoTrack(pc, stats.get()); + + Call::Stats call_stats; call_stats.send_bandwidth_bps = kSendBandwidth; call_stats.recv_bandwidth_bps = kRecvBandwidth; call_stats.pacer_delay_ms = kPacerDelay; - EXPECT_CALL(pc_, GetCallStats()).WillRepeatedly(Return(call_stats)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); + pc->SetCallStats(call_stats); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - std::string result = ExtractSsrcStatsValue(reports, - StatsReport::kStatsValueNameBytesSent); - EXPECT_EQ(kBytesSentString, result); - result = ExtractBweStatsValue( - reports, StatsReport::kStatsValueNameAvailableSendBandwidth); - EXPECT_EQ(rtc::ToString(kSendBandwidth), result); - result = ExtractBweStatsValue( - reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth); - EXPECT_EQ(rtc::ToString(kRecvBandwidth), result); - result = - ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay); - EXPECT_EQ(rtc::ToString(kPacerDelay), result); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); + + EXPECT_EQ( + rtc::ToString(kBytesSent), + ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent)); + EXPECT_EQ(rtc::ToString(kSendBandwidth), + ExtractBweStatsValue( + reports, StatsReport::kStatsValueNameAvailableSendBandwidth)); + EXPECT_EQ( + rtc::ToString(kRecvBandwidth), + ExtractBweStatsValue( + reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth)); + EXPECT_EQ( + rtc::ToString(kPacerDelay), + ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay)); } // This test verifies that an object of type "googSession" always // exists in the returned stats. TEST_F(StatsCollectorTest, SessionObjectExists) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - StatsReports reports; // returned values. - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - const StatsReport* session_report = FindNthReportByType( - reports, StatsReport::kStatsReportTypeSession, 1); - EXPECT_FALSE(session_report == NULL); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); + + EXPECT_TRUE( + FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1)); } // This test verifies that only one object of type "googSession" exists // in the returned stats. TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - StatsReports reports; // returned values. - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - const StatsReport* session_report = FindNthReportByType( - reports, StatsReport::kStatsReportTypeSession, 1); - EXPECT_FALSE(session_report == NULL); - session_report = FindNthReportByType( - reports, StatsReport::kStatsReportTypeSession, 2); - EXPECT_EQ(NULL, session_report); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); + + EXPECT_TRUE( + FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1)); + EXPECT_FALSE( + FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 2)); } // This test verifies that the empty track report exists in the returned stats // without calling StatsCollector::UpdateStats. TEST_P(StatsCollectorTrackTest, TrackObjectExistsWithoutUpdateStats) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - AddOutgoingVideoTrackStats(&stats); + pc->AddVideoChannel("video", "transport", VideoMediaInfo()); + AddOutgoingVideoTrack(pc, stats.get()); // Verfies the existence of the track report. StatsReports reports; - stats.GetStats(NULL, &reports); - ASSERT_EQ((size_t)1, reports.size()); + stats->GetStats(nullptr, &reports); + ASSERT_EQ(1u, reports.size()); EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type()); EXPECT_EQ(0, reports[0]->timestamp()); @@ -1211,62 +1021,41 @@ TEST_P(StatsCollectorTrackTest, TrackObjectExistsWithoutUpdateStats) { // This test verifies that the empty track report exists in the returned stats // when StatsCollector::UpdateStats is called with ssrc stats. TEST_P(StatsCollectorTrackTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { - StatsCollectorForTest stats(&pc_); + constexpr int64_t kBytesSent = 12345678901234LL; - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - AddOutgoingVideoTrackStats(&stats); - - // Constructs an ssrc stats update. - cricket::VideoSenderInfo video_sender_info; - cricket::VideoMediaInfo stats_read; - const int64_t kBytesSent = 12345678901234LL; - - // Construct a stats value to read. + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(1234); video_sender_info.bytes_sent = kBytesSent; - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + AddOutgoingVideoTrack(pc, stats.get()); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); + // |reports| should contain at least one session report, one track report, // and one ssrc report. - EXPECT_LE((size_t)3, reports.size()); + EXPECT_LE(3u, reports.size()); const StatsReport* track_report = FindNthReportByType( reports, StatsReport::kStatsReportTypeTrack, 1); EXPECT_TRUE(track_report); // Get report for the specific |track|. reports.clear(); - stats.GetStats(track_, &reports); + stats->GetStats(track_, &reports); // |reports| should contain at least one session report, one track report, // and one ssrc report. - EXPECT_LE((size_t)3, reports.size()); + EXPECT_LE(3u, reports.size()); track_report = FindNthReportByType( reports, StatsReport::kStatsReportTypeTrack, 1); ASSERT_TRUE(track_report); - EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); + EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); std::string ssrc_id = ExtractSsrcStatsValue( reports, StatsReport::kStatsValueNameSsrc); @@ -1284,49 +1073,30 @@ TEST_P(StatsCollectorTrackTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { // This test verifies that an SSRC object has the identifier of a Transport // stats object, and that this transport stats object exists in stats. TEST_P(StatsCollectorTrackTest, TransportObjectLinkedFromSsrcObject) { - StatsCollectorForTest stats(&pc_); + constexpr int64_t kBytesSent = 12345678901234LL; - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "vcname", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - AddOutgoingVideoTrackStats(&stats); - - // Constructs an ssrc stats update. - cricket::VideoSenderInfo video_sender_info; - cricket::VideoMediaInfo stats_read; - const int64_t kBytesSent = 12345678901234LL; - - // Construct a stats value to read. + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(1234); video_sender_info.bytes_sent = kBytesSent; - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + AddOutgoingVideoTrack(pc, stats.get()); - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); + std::string transport_id = ExtractStatsValue( StatsReport::kStatsReportTypeSsrc, reports, StatsReport::kStatsValueNameTransportId); ASSERT_NE(kNotFound, transport_id); + // Transport id component ID will always be 1. // This has assumptions about how the ID is constructed. As is, this is // OK since this is for testing purposes only, but if we ever need this @@ -1340,128 +1110,83 @@ TEST_P(StatsCollectorTrackTest, TransportObjectLinkedFromSsrcObject) { StatsReport::Id id(StatsReport::NewComponentId(content, 1)); ASSERT_EQ(transport_id, id->ToString()); const StatsReport* transport_report = FindReportById(reports, id); - ASSERT_FALSE(transport_report == NULL); + ASSERT_TRUE(transport_report); } // This test verifies that a remote stats object will not be created for // an outgoing SSRC where remote stats are not returned. TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsAbsent) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "vcname", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - AddOutgoingVideoTrackStats(&stats); + pc->AddVideoChannel("video", "transport", VideoMediaInfo()); + AddOutgoingVideoTrack(pc, stats.get()); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); + const StatsReport* remote_report = FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1); - EXPECT_TRUE(remote_report == NULL); + EXPECT_FALSE(remote_report); } // This test verifies that a remote stats object will be created for // an outgoing SSRC where stats are returned. TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsPresent) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVideoMediaChannel(); - // The transport_name known by the video channel. - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "vcname", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - AddOutgoingVideoTrackStats(&stats); - - // Instruct the session to return stats containing the transport channel. - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - // Constructs an ssrc stats update. - cricket::VideoMediaInfo stats_read; - - cricket::SsrcReceiverInfo remote_ssrc_stats; + SsrcReceiverInfo remote_ssrc_stats; remote_ssrc_stats.timestamp = 12345.678; remote_ssrc_stats.ssrc = kSsrcOfTrack; - cricket::VideoSenderInfo video_sender_info; + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(kSsrcOfTrack); video_sender_info.remote_stats.push_back(remote_ssrc_stats); - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + AddOutgoingVideoTrack(pc, stats.get()); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); const StatsReport* remote_report = FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1); - EXPECT_FALSE(remote_report == NULL); + ASSERT_TRUE(remote_report); EXPECT_EQ(12345.678, remote_report->timestamp()); } // This test verifies that the empty track report exists in the returned stats // when StatsCollector::UpdateStats is called with ssrc stats. TEST_P(StatsCollectorTrackTest, ReportsFromRemoteTrack) { - StatsCollectorForTest stats(&pc_); + constexpr int64_t kNumOfPacketsConcealed = 54321; - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - AddIncomingVideoTrackStats(&stats); - - // Constructs an ssrc stats update. - cricket::VideoReceiverInfo video_receiver_info; - cricket::VideoMediaInfo stats_read; - const int64_t kNumOfPacketsConcealed = 54321; - - // Construct a stats value to read. + VideoReceiverInfo video_receiver_info; video_receiver_info.add_ssrc(1234); video_receiver_info.packets_concealed = kNumOfPacketsConcealed; - stats_read.receivers.push_back(video_receiver_info); + VideoMediaInfo video_info; + video_info.receivers.push_back(video_receiver_info); + pc->AddVideoChannel("video", "transport", video_info); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + AddIncomingVideoTrack(pc, stats.get()); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); StatsReports reports; - stats.GetStats(NULL, &reports); + stats->GetStats(nullptr, &reports); + // |reports| should contain at least one session report, one track report, // and one ssrc report. - EXPECT_LE(static_cast(3), reports.size()); + EXPECT_LE(3u, reports.size()); const StatsReport* track_report = FindNthReportByType( reports, StatsReport::kStatsReportTypeTrack, 1); ASSERT_TRUE(track_report); - EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); + EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); std::string ssrc_id = ExtractSsrcStatsValue( reports, StatsReport::kStatsValueNameSsrc); @@ -1475,49 +1200,61 @@ TEST_P(StatsCollectorTrackTest, ReportsFromRemoteTrack) { // This test verifies the Ice Candidate report should contain the correct // information from local/remote candidates. TEST_F(StatsCollectorTest, IceCandidateReport) { - StatsCollectorForTest stats(&pc_); + const std::string kTransportName = "transport"; + const rtc::AdapterType kNetworkType = rtc::ADAPTER_TYPE_ETHERNET; + constexpr uint32_t kPriority = 1000; - StatsReports reports; // returned values. + constexpr int kLocalPort = 2000; + const std::string kLocalIp = "192.168.0.1"; + const rtc::SocketAddress kLocalAddress(kLocalIp, kLocalPort); - const int local_port = 2000; - const char local_ip[] = "192.168.0.1"; - const int remote_port = 2001; - const char remote_ip[] = "192.168.0.2"; + constexpr int kRemotePort = 2001; + const std::string kRemoteIp = "192.168.0.2"; + const rtc::SocketAddress kRemoteAddress(kRemoteIp, kRemotePort); - rtc::SocketAddress local_address(local_ip, local_port); - rtc::SocketAddress remote_address(remote_ip, remote_port); - rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; - uint32_t priority = 1000; + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - cricket::Candidate c; - EXPECT_GT(c.id().length(), 0u); - c.set_type(cricket::LOCAL_PORT_TYPE); - c.set_protocol(cricket::UDP_PROTOCOL_NAME); - c.set_address(local_address); - c.set_priority(priority); - c.set_network_type(network_type); - std::string report_id = AddCandidateReport(&stats, c, true)->id()->ToString(); - EXPECT_EQ("Cand-" + c.id(), report_id); + cricket::Candidate local; + EXPECT_GT(local.id().length(), 0u); + local.set_type(cricket::LOCAL_PORT_TYPE); + local.set_protocol(cricket::UDP_PROTOCOL_NAME); + local.set_address(kLocalAddress); + local.set_priority(kPriority); + local.set_network_type(kNetworkType); - c = cricket::Candidate(); - EXPECT_GT(c.id().length(), 0u); - c.set_type(cricket::PRFLX_PORT_TYPE); - c.set_protocol(cricket::UDP_PROTOCOL_NAME); - c.set_address(remote_address); - c.set_priority(priority); - c.set_network_type(network_type); - report_id = AddCandidateReport(&stats, c, false)->id()->ToString(); - EXPECT_EQ("Cand-" + c.id(), report_id); + cricket::Candidate remote; + EXPECT_GT(remote.id().length(), 0u); + remote.set_type(cricket::PRFLX_PORT_TYPE); + remote.set_protocol(cricket::UDP_PROTOCOL_NAME); + remote.set_address(kRemoteAddress); + remote.set_priority(kPriority); + remote.set_network_type(kNetworkType); - stats.GetStats(NULL, &reports); + ConnectionInfo connection_info; + connection_info.local_candidate = local; + connection_info.remote_candidate = remote; + TransportChannelStats channel_stats; + channel_stats.connection_infos.push_back(connection_info); + + pc->AddVoiceChannel("audio", kTransportName, VoiceMediaInfo()); + pc->SetTransportStats(kTransportName, channel_stats); + + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); // Verify the local candidate report is populated correctly. EXPECT_EQ( - local_ip, + "Cand-" + local.id(), + ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports, + StatsReport::kStatsValueNameLocalCandidateId)); + EXPECT_EQ( + kLocalIp, ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidateIPAddress)); EXPECT_EQ( - rtc::ToString(local_port), + rtc::ToString(kLocalPort), ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidatePortNumber)); EXPECT_EQ( @@ -1525,7 +1262,7 @@ TEST_F(StatsCollectorTest, IceCandidateReport) { ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidateTransportType)); EXPECT_EQ( - rtc::ToString(priority), + rtc::ToString(kPriority), ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidatePriority)); EXPECT_EQ( @@ -1533,16 +1270,20 @@ TEST_F(StatsCollectorTest, IceCandidateReport) { ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidateType)); EXPECT_EQ( - AdapterTypeToStatsType(network_type), + AdapterTypeToStatsType(kNetworkType), ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, StatsReport::kStatsValueNameCandidateNetworkType)); // Verify the remote candidate report is populated correctly. - EXPECT_EQ(remote_ip, + EXPECT_EQ( + "Cand-" + remote.id(), + ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports, + StatsReport::kStatsValueNameRemoteCandidateId)); + EXPECT_EQ(kRemoteIp, ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, reports, StatsReport::kStatsValueNameCandidateIPAddress)); - EXPECT_EQ(rtc::ToString(remote_port), + EXPECT_EQ(rtc::ToString(kRemotePort), ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, reports, StatsReport::kStatsValueNameCandidatePortNumber)); @@ -1550,7 +1291,7 @@ TEST_F(StatsCollectorTest, IceCandidateReport) { ExtractStatsValue( StatsReport::kStatsReportTypeIceRemoteCandidate, reports, StatsReport::kStatsValueNameCandidateTransportType)); - EXPECT_EQ(rtc::ToString(priority), + EXPECT_EQ(rtc::ToString(kPriority), ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, reports, StatsReport::kStatsValueNameCandidatePriority)); @@ -1609,35 +1350,16 @@ TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { // This test verifies that the stats are generated correctly when no // transport is present. TEST_F(StatsCollectorTest, NoTransport) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + // This will cause the fake PeerConnection to generate a TransportStats entry + // but with only a single dummy TransportChannelStats. + pc->AddVoiceChannel("audio", "transport", VoiceMediaInfo()); - StatsReports reports; // returned values. - - // Fake stats to process. - cricket::TransportChannelStats channel_stats; - channel_stats.component = 1; - - cricket::TransportStats transport_stats; - transport_stats.transport_name = "audio"; - transport_stats.channel_stats.push_back(channel_stats); - - SessionStats session_stats; - session_stats.transport_stats[transport_stats.transport_name] = - transport_stats; - - // Configure MockWebRtcSession - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats)); - })); - - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); // Check that the local certificate is absent. std::string local_certificate_id = ExtractStatsValue( @@ -1664,53 +1386,6 @@ TEST_F(StatsCollectorTest, NoTransport) { ASSERT_EQ(kNotFound, srtp_crypto_suite); } -// This test verifies that the stats are generated correctly when the transport -// does not have any certificates. -TEST_F(StatsCollectorTest, NoCertificates) { - StatsCollectorForTest stats(&pc_); - - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - StatsReports reports; // returned values. - - // Fake stats to process. - cricket::TransportChannelStats channel_stats; - channel_stats.component = 1; - - cricket::TransportStats transport_stats; - transport_stats.transport_name = "audio"; - transport_stats.channel_stats.push_back(channel_stats); - - SessionStats session_stats; - session_stats.transport_stats[transport_stats.transport_name] = - transport_stats; - - // Configure MockWebRtcSession - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats)); - })); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); - - // Check that the local certificate is absent. - std::string local_certificate_id = ExtractStatsValue( - StatsReport::kStatsReportTypeComponent, - reports, - StatsReport::kStatsValueNameLocalCertificateId); - ASSERT_EQ(kNotFound, local_certificate_id); - - // Check that the remote certificate is absent. - std::string remote_certificate_id = ExtractStatsValue( - StatsReport::kStatsReportTypeComponent, - reports, - StatsReport::kStatsValueNameRemoteCertificateId); - ASSERT_EQ(kNotFound, remote_certificate_id); -} - // This test verifies that a remote certificate with an unsupported digest // algorithm is correctly ignored. TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { @@ -1731,55 +1406,37 @@ TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { // This test verifies that the audio/video related stats which are -1 initially // will be filtered out. TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) { - StatsCollectorForTest stats(&pc_); - // This test uses streams, but only works for the stream case. - if (!GetParam()) + if (!GetParam()) { return; - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + } - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); // Create a local stream with a local audio track and adds it to the stats. - if (stream_ == NULL) - stream_ = webrtc::MediaStream::Create("streamlabel"); - + stream_ = MediaStream::Create("streamlabel"); rtc::scoped_refptr local_track( new rtc::RefCountedObject(kLocalTrackId)); stream_->AddTrack(local_track); - EXPECT_CALL(pc_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); + pc->AddLocalTrack(kSsrcOfTrack, kLocalTrackId); if (GetParam()) { - stats.AddStream(stream_); + stats->AddStream(stream_); } - stats.AddLocalAudioTrack(local_track.get(), kSsrcOfTrack); + stats->AddLocalAudioTrack(local_track.get(), kSsrcOfTrack); // Create a remote stream with a remote audio track and adds it to the stats. - rtc::scoped_refptr remote_stream( - webrtc::MediaStream::Create("remotestreamlabel")); + rtc::scoped_refptr remote_stream( + MediaStream::Create("remotestreamlabel")); rtc::scoped_refptr remote_track( new rtc::RefCountedObject(kRemoteTrackId)); - EXPECT_CALL(pc_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); remote_stream->AddTrack(remote_track); + pc->AddRemoteTrack(kSsrcOfTrack, kRemoteTrackId); if (GetParam()) { - stats.AddStream(remote_stream); + stats->AddStream(remote_stream); } - InitSessionStats(&voice_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - cricket::VoiceSenderInfo voice_sender_info; + VoiceSenderInfo voice_sender_info; voice_sender_info.add_ssrc(kSsrcOfTrack); // These values are set to -1 initially in audio_send_stream. // The voice_sender_info will read the values from audio_send_stream. @@ -1792,26 +1449,23 @@ TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) { UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &voice_sender_info, true); - cricket::VoiceReceiverInfo voice_receiver_info; + VoiceReceiverInfo voice_receiver_info; voice_receiver_info.add_ssrc(kSsrcOfTrack); voice_receiver_info.capture_start_ntp_time_ms = -1; voice_receiver_info.audio_level = -1; // Constructs an ssrc stats update. - cricket::VoiceMediaInfo stats_read; - stats_read.senders.push_back(voice_sender_info); - stats_read.receivers.push_back(voice_receiver_info); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); + voice_info.receivers.push_back(voice_receiver_info); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(Return(&voice_channel)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), Return(true))); + pc->AddVoiceChannel("voice", "transport", voice_info); - StatsReports reports; - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); // Get stats for the local track. - stats.GetStats(local_track.get(), &reports); + StatsReports reports; + stats->GetStats(local_track.get(), &reports); const StatsReport* report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1); ASSERT_TRUE(report); @@ -1830,7 +1484,7 @@ TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) { // Get stats for the remote track. reports.clear(); - stats.GetStats(remote_track.get(), &reports); + stats->GetStats(remote_track.get(), &reports); report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1); ASSERT_TRUE(report); EXPECT_FALSE(GetValue(report, @@ -1843,28 +1497,21 @@ TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) { // This test verifies that a local stats object can get statistics via // AudioTrackInterface::GetStats() method. TEST_P(StatsCollectorTrackTest, GetStatsFromLocalAudioTrack) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + AddOutgoingAudioTrack(pc, stats.get()); + stats->AddLocalAudioTrack(audio_track_, kSsrcOfTrack); - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); - AddOutgoingAudioTrackStats(&stats); - stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); - - cricket::VoiceSenderInfo voice_sender_info; + VoiceSenderInfo voice_sender_info; InitVoiceSenderInfo(&voice_sender_info); + UpdateVoiceSenderInfoFromAudioTrack(audio_track_, &voice_sender_info, false); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); + pc->AddVoiceChannel("audio", "transport", voice_info); - cricket::VoiceMediaInfo stats_read; StatsReports reports; // returned values. - SetupAndVerifyAudioTrackStats( - audio_track_.get(), stream_.get(), &stats, &voice_channel, media_channel, - &voice_sender_info, NULL, &stats_read, &reports); + VerifyAudioTrackStats(audio_track_, stats.get(), voice_info, &reports); // Verify that there is no remote report for the local audio track because // we did not set it up. @@ -1876,77 +1523,49 @@ TEST_P(StatsCollectorTrackTest, GetStatsFromLocalAudioTrack) { // This test verifies that audio receive streams populate stats reports // correctly. TEST_P(StatsCollectorTrackTest, GetStatsFromRemoteStream) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + AddIncomingAudioTrack(pc, stats.get()); - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); - AddIncomingAudioTrackStats(&stats); - - cricket::VoiceReceiverInfo voice_receiver_info; + VoiceReceiverInfo voice_receiver_info; InitVoiceReceiverInfo(&voice_receiver_info); voice_receiver_info.codec_name = "fake_codec"; + VoiceMediaInfo voice_info; + voice_info.receivers.push_back(voice_receiver_info); + pc->AddVoiceChannel("audio", "transport", voice_info); - cricket::VoiceMediaInfo stats_read; StatsReports reports; // returned values. - SetupAndVerifyAudioTrackStats(audio_track_.get(), stream_.get(), &stats, - &voice_channel, media_channel, NULL, - &voice_receiver_info, &stats_read, &reports); + VerifyAudioTrackStats(audio_track_, stats.get(), voice_info, &reports); } // This test verifies that a local stats object won't update its statistics // after a RemoveLocalAudioTrack() call. TEST_P(StatsCollectorTrackTest, GetStatsAfterRemoveAudioStream) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + AddOutgoingAudioTrack(pc, stats.get()); + stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); - AddOutgoingAudioTrackStats(&stats); - stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); - - InitSessionStats(&voice_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); - cricket::VoiceSenderInfo voice_sender_info; + VoiceSenderInfo voice_sender_info; InitVoiceSenderInfo(&voice_sender_info); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); - // Constructs an ssrc stats update. - cricket::VoiceMediaInfo stats_read; - stats_read.senders.push_back(voice_sender_info); + pc->AddVoiceChannel("audio", "transport", voice_info); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(Return(&voice_channel)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); - StatsReports reports; // returned values. - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); // The report will exist since we don't remove them in RemoveStream(). const StatsReport* report = FindNthReportByType( reports, StatsReport::kStatsReportTypeSsrc, 1); - EXPECT_FALSE(report == NULL); - EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); + ASSERT_TRUE(report); + EXPECT_EQ(stats->GetTimeNow(), report->timestamp()); std::string track_id = ExtractSsrcStatsValue( reports, StatsReport::kStatsValueNameTrackId); EXPECT_EQ(kLocalTrackId, track_id); @@ -1963,71 +1582,50 @@ TEST_P(StatsCollectorTrackTest, GetStatsAfterRemoveAudioStream) { // This test verifies that when ongoing and incoming audio tracks are using // the same ssrc, they populate stats reports correctly. TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) { - StatsCollectorForTest stats(&pc_); - - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); // Create a local stream with a local audio track and adds it to the stats. - AddOutgoingAudioTrackStats(&stats); - stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + AddOutgoingAudioTrack(pc, stats.get()); + stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); // Create a remote stream with a remote audio track and adds it to the stats. - rtc::scoped_refptr remote_stream( - webrtc::MediaStream::Create("remotestreamlabel")); + rtc::scoped_refptr remote_stream( + MediaStream::Create("remotestreamlabel")); rtc::scoped_refptr remote_track( new rtc::RefCountedObject(kRemoteTrackId)); - EXPECT_CALL(pc_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); + pc->AddRemoteTrack(kSsrcOfTrack, kRemoteTrackId); remote_stream->AddTrack(remote_track); - stats.AddStream(remote_stream); + stats->AddStream(remote_stream); - // Instruct the session to return stats containing the transport channel. - InitSessionStats(&voice_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - cricket::VoiceSenderInfo voice_sender_info; + VoiceSenderInfo voice_sender_info; InitVoiceSenderInfo(&voice_sender_info); - // Some of the contents in |voice_sender_info| needs to be updated from the // |audio_track_|. UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info, true); - cricket::VoiceReceiverInfo voice_receiver_info; + VoiceReceiverInfo voice_receiver_info; InitVoiceReceiverInfo(&voice_receiver_info); // Constructs an ssrc stats update. - cricket::VoiceMediaInfo stats_read; - stats_read.senders.push_back(voice_sender_info); - stats_read.receivers.push_back(voice_receiver_info); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); + voice_info.receivers.push_back(voice_receiver_info); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(Return(&voice_channel)); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), - Return(true))); + // Instruct the session to return stats containing the transport channel. + pc->AddVoiceChannel("audio", "transport", voice_info); - StatsReports reports; // returned values. - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); // Get stats for the local track. - stats.GetStats(audio_track_.get(), &reports); + StatsReports reports; // returned values. + stats->GetStats(audio_track_.get(), &reports); + const StatsReport* track_report = FindNthReportByType( reports, StatsReport::kStatsReportTypeSsrc, 1); ASSERT_TRUE(track_report); - EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); + EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); std::string track_id = ExtractSsrcStatsValue( reports, StatsReport::kStatsValueNameTrackId); EXPECT_EQ(kLocalTrackId, track_id); @@ -2035,11 +1633,11 @@ TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) { // Get stats for the remote track. reports.clear(); - stats.GetStats(remote_track.get(), &reports); + stats->GetStats(remote_track.get(), &reports); track_report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1); ASSERT_TRUE(track_report); - EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); + EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); track_id = ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId); EXPECT_EQ(kRemoteTrackId, track_id); @@ -2051,97 +1649,74 @@ TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) { // TODO(xians): Figure out if it is possible to encapsulate the setup and // avoid duplication of code in test cases. TEST_P(StatsCollectorTrackTest, TwoLocalTracksWithSameSsrc) { - StatsCollectorForTest stats(&pc_); - // This test only makes sense when we're using streams. - if (!GetParam()) + if (!GetParam()) { return; + } - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); - - auto* media_channel = new MockVoiceMediaChannel(); - cricket::VoiceChannel voice_channel( - worker_thread_, network_thread_, nullptr, media_engine_, - rtc::WrapUnique(media_channel), "vcname", kDefaultRtcpMuxRequired, - kDefaultSrtpRequired); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); // Create a local stream with a local audio track and adds it to the stats. - AddOutgoingAudioTrackStats(&stats); - stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); + AddOutgoingAudioTrack(pc, stats.get()); + stats->AddLocalAudioTrack(audio_track_, kSsrcOfTrack); - cricket::VoiceSenderInfo voice_sender_info; + VoiceSenderInfo voice_sender_info; InitVoiceSenderInfo(&voice_sender_info); + UpdateVoiceSenderInfoFromAudioTrack(audio_track_, &voice_sender_info, false); voice_sender_info.add_ssrc(kSsrcOfTrack); + VoiceMediaInfo voice_info; + voice_info.senders.push_back(voice_sender_info); + auto* media_channel = pc->AddVoiceChannel("voice", "transport", voice_info); - cricket::VoiceMediaInfo stats_read; StatsReports reports; // returned values. - SetupAndVerifyAudioTrackStats( - audio_track_.get(), stream_.get(), &stats, &voice_channel, media_channel, - &voice_sender_info, NULL, &stats_read, &reports); + VerifyAudioTrackStats(audio_track_, stats.get(), voice_info, &reports); // Remove the previous audio track from the stream. stream_->RemoveTrack(audio_track_.get()); - stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); // Create a new audio track and adds it to the stream and stats. static const std::string kNewTrackId = "new_track_id"; rtc::scoped_refptr new_audio_track( new rtc::RefCountedObject(kNewTrackId)); - EXPECT_CALL(pc_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) - .WillOnce(DoAll(SetArgPointee<1>(kNewTrackId), Return(true))); + pc->AddLocalTrack(kSsrcOfTrack, kNewTrackId); stream_->AddTrack(new_audio_track); - stats.AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); - stats.ClearUpdateStatsCacheForTest(); - cricket::VoiceSenderInfo new_voice_sender_info; + stats->AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); + stats->ClearUpdateStatsCacheForTest(); + + VoiceSenderInfo new_voice_sender_info; InitVoiceSenderInfo(&new_voice_sender_info); - cricket::VoiceMediaInfo new_stats_read; + UpdateVoiceSenderInfoFromAudioTrack(new_audio_track, &new_voice_sender_info, + false); + VoiceMediaInfo new_voice_info; + new_voice_info.senders.push_back(new_voice_sender_info); + media_channel->SetStats(new_voice_info); + reports.clear(); - SetupAndVerifyAudioTrackStats( - new_audio_track.get(), stream_.get(), &stats, &voice_channel, - media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); + VerifyAudioTrackStats(new_audio_track, stats.get(), new_voice_info, &reports); } // This test verifies that stats are correctly set in video send ssrc stats. TEST_P(StatsCollectorTrackTest, VerifyVideoSendSsrcStats) { - StatsCollectorForTest stats(&pc_); + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + AddOutgoingVideoTrack(pc, stats.get()); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - StatsReports reports; // returned values. - cricket::VideoSenderInfo video_sender_info; - cricket::VideoMediaInfo stats_read; - - AddOutgoingVideoTrackStats(&stats); - - // Construct a stats value to read. + VideoSenderInfo video_sender_info; video_sender_info.add_ssrc(1234); video_sender_info.frames_encoded = 10; video_sender_info.qp_sum = 11; - stats_read.senders.push_back(video_sender_info); + VideoMediaInfo video_info; + video_info.senders.push_back(video_sender_info); + pc->AddVideoChannel("video", "transport", video_info); + + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); EXPECT_EQ(rtc::ToString(video_sender_info.frames_encoded), ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameFramesEncoded)); @@ -2150,43 +1725,24 @@ TEST_P(StatsCollectorTrackTest, VerifyVideoSendSsrcStats) { } // This test verifies that stats are correctly set in video receive ssrc stats. -TEST_P(StatsCollectorTrackTest, VerifyVideoReceiveSsrcStats) { - StatsCollectorForTest stats(&pc_); +TEST_P(StatsCollectorTrackTest, VerifyVideoReceiveSsrcStatsNew) { + auto pc = CreatePeerConnection(); + auto stats = CreateStatsCollector(pc); - EXPECT_CALL(pc_, GetLocalCertificate(_, _)).WillRepeatedly(Return(false)); - EXPECT_CALL(pc_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) - .WillRepeatedly(Return(nullptr)); + AddIncomingVideoTrack(pc, stats.get()); - auto* media_channel = new MockVideoMediaChannel(); - cricket::VideoChannel video_channel( - worker_thread_, network_thread_, nullptr, rtc::WrapUnique(media_channel), - "video", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); - - InitSessionStats(&video_channel); - EXPECT_CALL(pc_, GetSessionStats(_)) - .WillRepeatedly(Invoke([this](const ChannelNamePairs&) { - return std::unique_ptr( - new SessionStats(session_stats_)); - })); - - StatsReports reports; // returned values. - cricket::VideoReceiverInfo video_receiver_info; - cricket::VideoMediaInfo stats_read; - - AddIncomingVideoTrackStats(&stats); - - // Construct a stats value to read. + VideoReceiverInfo video_receiver_info; video_receiver_info.add_ssrc(1234); video_receiver_info.frames_decoded = 10; video_receiver_info.qp_sum = 11; - stats_read.receivers.push_back(video_receiver_info); + VideoMediaInfo video_info; + video_info.receivers.push_back(video_receiver_info); + pc->AddVideoChannel("video", "transport", video_info); + + stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; + stats->GetStats(nullptr, &reports); - EXPECT_CALL(pc_, video_channel()).WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(pc_, voice_channel()).WillRepeatedly(ReturnNull()); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); - stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); - stats.GetStats(NULL, &reports); EXPECT_EQ(rtc::ToString(video_receiver_info.frames_decoded), ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameFramesDecoded)); diff --git a/pc/test/fakepeerconnectionforstats.h b/pc/test/fakepeerconnectionforstats.h new file mode 100644 index 0000000000..7d99ba38c5 --- /dev/null +++ b/pc/test/fakepeerconnectionforstats.h @@ -0,0 +1,303 @@ +/* + * 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/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()) {} + + FakeVoiceMediaChannelForStats* AddVoiceChannel( + const std::string& mid, + const std::string& transport_name, + const cricket::VoiceMediaInfo& voice_info) { + 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, kDefaultRtcpMuxRequired, + kDefaultSrtpRequired); + voice_channel_->set_transport_name_for_testing(transport_name); + voice_media_channel_ptr->SetStats(voice_info); + return voice_media_channel_ptr; + } + + FakeVideoMediaChannelForStats* AddVideoChannel( + const std::string& mid, + const std::string& transport_name, + const cricket::VideoMediaInfo& video_stats) { + 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, kDefaultRtcpMuxRequired, + kDefaultSrtpRequired); + video_channel_->set_transport_name_for_testing(transport_name); + video_media_channel_ptr->SetStats(video_stats); + 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) { + sctp_data_channels_.push_back(DataChannel::Create( + &data_channel_provider_, cricket::DCT_SCTP, label, init)); + } + + void SetTransportStats(const std::string& transport_name, + const cricket::TransportChannelStats& channel_stats) { + cricket::TransportStats transport_stats; + transport_stats.transport_name = transport_name; + transport_stats.channel_stats.push_back(channel_stats); + 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 SetRemoteCertificate(const std::string& transport_name, + std::unique_ptr certificate) { + remote_certificates_by_transport_[transport_name] = std::move(certificate); + } + + // 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_; } + + cricket::VoiceChannel* voice_channel() const override { + return voice_channel_.get(); + } + + cricket::VideoChannel* video_channel() const override { + return video_channel_.get(); + } + + 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_; + } + + std::unique_ptr GetSessionStats_s() override { + std::set transport_names; + if (voice_channel_) { + transport_names.insert(voice_channel_->transport_name()); + } + if (video_channel_) { + transport_names.insert(video_channel_->transport_name()); + } + return GetSessionStatsForTransports(transport_names); + } + + std::unique_ptr GetSessionStats( + const ChannelNamePairs& channel_name_pairs) override { + std::set transport_names; + if (channel_name_pairs.voice) { + transport_names.insert(channel_name_pairs.voice.value().transport_name); + } + if (channel_name_pairs.video) { + transport_names.insert(channel_name_pairs.video.value().transport_name); + } + if (channel_name_pairs.data) { + transport_names.insert(channel_name_pairs.data.value().transport_name); + } + return GetSessionStatsForTransports(transport_names); + } + + 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 GetRemoteSSLCertificate( + const std::string& transport_name) override { + auto it = remote_certificates_by_transport_.find(transport_name); + if (it != remote_certificates_by_transport_.end()) { + return it->second->GetUniqueReference(); + } else { + return nullptr; + } + } + + private: + std::unique_ptr GetSessionStatsForTransports( + const std::set& transport_names) { + auto stats = rtc::MakeUnique(); + for (const std::string& transport_name : transport_names) { + stats->transport_stats[transport_name] = + GetTransportStatsByName(transport_name); + } + return stats; + } + + 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 = 1; + cricket::TransportStats transport_stats; + transport_stats.transport_name = transport_name; + transport_stats.channel_stats.push_back(channel_stats); + return transport_stats; + } + + rtc::Thread* const network_thread_; + rtc::Thread* const worker_thread_; + rtc::Thread* const signaling_thread_; + + 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_certificates_by_transport_; +}; + +} // namespace webrtc + +#endif // PC_TEST_FAKEPEERCONNECTIONFORSTATS_H_