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_