diff options
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc')
-rw-r--r-- | chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc | 938 |
1 files changed, 791 insertions, 147 deletions
diff --git a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc index 1adcb0e20aa..2cd716e0232 100644 --- a/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc +++ b/chromium/third_party/libjingle/source/talk/app/webrtc/statscollector_unittest.cc @@ -1,5 +1,6 @@ /* * libjingle + * Copyright 2014, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -29,6 +30,8 @@ #include "talk/app/webrtc/statscollector.h" #include "talk/app/webrtc/mediastream.h" +#include "talk/app/webrtc/mediastreaminterface.h" +#include "talk/app/webrtc/mediastreamtrack.h" #include "talk/app/webrtc/videotrack.h" #include "talk/base/base64.h" #include "talk/base/fakesslidentity.h" @@ -37,13 +40,19 @@ #include "talk/media/devices/fakedevicemanager.h" #include "talk/p2p/base/fakesession.h" #include "talk/session/media/channelmanager.h" -#include "testing/base/public/gmock.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +using cricket::StatsOptions; using testing::_; using testing::DoAll; +using testing::Field; using testing::Return; using testing::ReturnNull; using testing::SetArgPointee; +using webrtc::PeerConnectionInterface; +using webrtc::StatsReport; +using webrtc::StatsReports; namespace cricket { @@ -59,7 +68,8 @@ const char kNotFound[] = "NOT FOUND"; const char kNoReports[] = "NO REPORTS"; // Constant names for track identification. -const char kTrackId[] = "somename"; +const char kLocalTrackId[] = "local_track_id"; +const char kRemoteTrackId[] = "remote_track_id"; const uint32 kSsrcOfTrack = 1234; class MockWebRtcSession : public webrtc::WebRtcSession { @@ -68,8 +78,12 @@ class MockWebRtcSession : public webrtc::WebRtcSession { : WebRtcSession(channel_manager, talk_base::Thread::Current(), talk_base::Thread::Current(), NULL, NULL) { } + MOCK_METHOD0(voice_channel, cricket::VoiceChannel*()); MOCK_METHOD0(video_channel, cricket::VideoChannel*()); - MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*)); + // Libjingle uses "local" for a outgoing track, and "remote" for a incoming + // track. + MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32, std::string*)); + MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32, std::string*)); MOCK_METHOD1(GetStats, bool(cricket::SessionStats*)); MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&)); }; @@ -80,13 +94,64 @@ class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel { : cricket::FakeVideoMediaChannel(NULL) { } // MOCK_METHOD0(transport_channel, cricket::TransportChannel*()); - MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*)); + MOCK_METHOD2(GetStats, bool(const StatsOptions&, cricket::VideoMediaInfo*)); }; -bool GetValue(const webrtc::StatsReport* report, +class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel { + public: + MockVoiceMediaChannel() : cricket::FakeVoiceMediaChannel(NULL) { + } + MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*)); +}; + +class FakeAudioProcessor : public webrtc::AudioProcessorInterface { + public: + FakeAudioProcessor() {} + ~FakeAudioProcessor() {} + + private: + virtual void GetStats( + AudioProcessorInterface::AudioProcessorStats* stats) OVERRIDE { + stats->typing_noise_detected = true; + stats->echo_return_loss = 2; + stats->echo_return_loss_enhancement = 3; + stats->echo_delay_median_ms = 4; + stats->aec_quality_min = 5.1f; + stats->echo_delay_std_ms = 6; + } +}; + +class FakeAudioTrack + : public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface> { + public: + explicit FakeAudioTrack(const std::string& id) + : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id), + processor_(new talk_base::RefCountedObject<FakeAudioProcessor>()) {} + std::string kind() const OVERRIDE { + return "audio"; + } + virtual webrtc::AudioSourceInterface* GetSource() const OVERRIDE { + return NULL; + } + virtual void AddSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {} + virtual void RemoveSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {} + virtual bool GetSignalLevel(int* level) OVERRIDE { + *level = 1; + return true; + } + virtual talk_base::scoped_refptr<webrtc::AudioProcessorInterface> + GetAudioProcessor() OVERRIDE { + return processor_; + } + + private: + talk_base::scoped_refptr<FakeAudioProcessor> processor_; +}; + +bool GetValue(const StatsReport* report, const std::string& name, std::string* value) { - webrtc::StatsReport::Values::const_iterator it = report->values.begin(); + StatsReport::Values::const_iterator it = report->values.begin(); for (; it != report->values.end(); ++it) { if (it->name == name) { *value = it->value; @@ -97,7 +162,7 @@ bool GetValue(const webrtc::StatsReport* report, } std::string ExtractStatsValue(const std::string& type, - const webrtc::StatsReports& reports, + const StatsReports& reports, const std::string name) { if (reports.empty()) { return kNoReports; @@ -116,8 +181,8 @@ std::string ExtractStatsValue(const std::string& type, // Finds the |n|-th report of type |type| in |reports|. // |n| starts from 1 for finding the first report. -const webrtc::StatsReport* FindNthReportByType( - const webrtc::StatsReports& reports, const std::string& type, int n) { +const StatsReport* FindNthReportByType( + const StatsReports& reports, const std::string& type, int n) { for (size_t i = 0; i < reports.size(); ++i) { if (reports[i].type == type) { n--; @@ -128,8 +193,8 @@ const webrtc::StatsReport* FindNthReportByType( return NULL; } -const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports, - const std::string& id) { +const StatsReport* FindReportById(const StatsReports& reports, + const std::string& id) { for (size_t i = 0; i < reports.size(); ++i) { if (reports[i].id == id) { return &reports[i]; @@ -138,16 +203,16 @@ const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports, return NULL; } -std::string ExtractSsrcStatsValue(webrtc::StatsReports reports, +std::string ExtractSsrcStatsValue(StatsReports reports, const std::string& name) { return ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeSsrc, reports, name); + StatsReport::kStatsReportTypeSsrc, reports, name); } -std::string ExtractBweStatsValue(webrtc::StatsReports reports, +std::string ExtractBweStatsValue(StatsReports reports, const std::string& name) { return ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeBwe, reports, name); + StatsReport::kStatsReportTypeBwe, reports, name); } std::string DerToPem(const std::string& der) { @@ -164,18 +229,18 @@ std::vector<std::string> DersToPems( return pems; } -void CheckCertChainReports(const webrtc::StatsReports& reports, +void CheckCertChainReports(const StatsReports& reports, const std::vector<std::string>& ders, const std::string& start_id) { std::string certificate_id = start_id; size_t i = 0; while (true) { - const webrtc::StatsReport* report = FindReportById(reports, certificate_id); + const StatsReport* report = FindReportById(reports, certificate_id); ASSERT_TRUE(report != NULL); std::string der_base64; EXPECT_TRUE(GetValue( - report, webrtc::StatsReport::kStatsValueNameDer, &der_base64)); + report, StatsReport::kStatsValueNameDer, &der_base64)); std::string der = talk_base::Base64::Decode(der_base64, talk_base::Base64::DO_STRICT); EXPECT_EQ(ders[i], der); @@ -183,7 +248,7 @@ void CheckCertChainReports(const webrtc::StatsReports& reports, std::string fingerprint_algorithm; EXPECT_TRUE(GetValue( report, - webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm, + StatsReport::kStatsValueNameFingerprintAlgorithm, &fingerprint_algorithm)); // The digest algorithm for a FakeSSLCertificate is always SHA-1. std::string sha_1_str = talk_base::DIGEST_SHA_1; @@ -192,17 +257,179 @@ void CheckCertChainReports(const webrtc::StatsReports& reports, std::string dummy_fingerprint; // Value is not checked. EXPECT_TRUE(GetValue( report, - webrtc::StatsReport::kStatsValueNameFingerprint, + StatsReport::kStatsValueNameFingerprint, &dummy_fingerprint)); ++i; if (!GetValue( - report, webrtc::StatsReport::kStatsValueNameIssuerId, &certificate_id)) + report, StatsReport::kStatsValueNameIssuerId, &certificate_id)) break; } EXPECT_EQ(ders.size(), i); } +void VerifyVoiceReceiverInfoReport( + const StatsReport* report, + const cricket::VoiceReceiverInfo& info) { + std::string value_in_report; + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameAudioOutputLevel, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.audio_level), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameBytesReceived, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int64>(info.bytes_rcvd), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.jitter_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameJitterBufferMs, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.jitter_buffer_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNamePreferredJitterBufferMs, + &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.jitter_buffer_preferred_ms), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameCurrentDelayMs, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.delay_estimate_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameExpandRate, &value_in_report)); + EXPECT_EQ(talk_base::ToString<float>(info.expand_rate), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNamePacketsReceived, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.packets_rcvd), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingCTSG, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_calls_to_silence_generator), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingCTN, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_calls_to_neteq), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingNormal, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_normal), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingPLC, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_plc), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingCNG, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_cng), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(info.decoding_plc_cng), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameCodecName, &value_in_report)); +} + + +void VerifyVoiceSenderInfoReport(const StatsReport* report, + const cricket::VoiceSenderInfo& sinfo) { + std::string value_in_report; + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameCodecName, &value_in_report)); + EXPECT_EQ(sinfo.codec_name, value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameBytesSent, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int64>(sinfo.bytes_sent), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNamePacketsSent, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_sent), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNamePacketsLost, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_lost), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameRtt, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameRtt, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.jitter_ms), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameEchoCancellationQualityMin, + &value_in_report)); + EXPECT_EQ(talk_base::ToString<float>(sinfo.aec_quality_min), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_median_ms), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_std_ms), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameEchoReturnLossEnhancement, + &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss_enhancement), + value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report)); + EXPECT_EQ(talk_base::ToString<int>(sinfo.audio_level), value_in_report); + EXPECT_TRUE(GetValue( + report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report)); + std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false"; + EXPECT_EQ(typing_detected, value_in_report); +} + +// Helper methods to avoid duplication of code. +void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info) { + voice_sender_info->add_ssrc(kSsrcOfTrack); + voice_sender_info->codec_name = "fake_codec"; + voice_sender_info->bytes_sent = 100; + voice_sender_info->packets_sent = 101; + voice_sender_info->rtt_ms = 102; + voice_sender_info->fraction_lost = 103; + voice_sender_info->jitter_ms = 104; + voice_sender_info->packets_lost = 105; + voice_sender_info->ext_seqnum = 106; + voice_sender_info->audio_level = 107; + voice_sender_info->echo_return_loss = 108; + voice_sender_info->echo_return_loss_enhancement = 109; + voice_sender_info->echo_delay_median_ms = 110; + voice_sender_info->echo_delay_std_ms = 111; + voice_sender_info->aec_quality_min = 112.0f; + voice_sender_info->typing_noise_detected = false; +} + +void UpdateVoiceSenderInfoFromAudioTrack( + FakeAudioTrack* audio_track, cricket::VoiceSenderInfo* voice_sender_info) { + audio_track->GetSignalLevel(&voice_sender_info->audio_level); + webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats; + audio_track->GetAudioProcessor()->GetStats(&audio_processor_stats); + voice_sender_info->typing_noise_detected = + audio_processor_stats.typing_noise_detected; + voice_sender_info->echo_return_loss = audio_processor_stats.echo_return_loss; + voice_sender_info->echo_return_loss_enhancement = + audio_processor_stats.echo_return_loss_enhancement; + voice_sender_info->echo_delay_median_ms = + audio_processor_stats.echo_delay_median_ms; + voice_sender_info->aec_quality_min = audio_processor_stats.aec_quality_min; + voice_sender_info->echo_delay_std_ms = + audio_processor_stats.echo_delay_std_ms; +} + +void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) { + voice_receiver_info->add_ssrc(kSsrcOfTrack); + voice_receiver_info->bytes_rcvd = 110; + voice_receiver_info->packets_rcvd = 111; + voice_receiver_info->packets_lost = 112; + voice_receiver_info->fraction_lost = 113; + voice_receiver_info->packets_lost = 114; + voice_receiver_info->ext_seqnum = 115; + voice_receiver_info->jitter_ms = 116; + voice_receiver_info->jitter_buffer_ms = 117; + voice_receiver_info->jitter_buffer_preferred_ms = 118; + voice_receiver_info->delay_estimate_ms = 119; + voice_receiver_info->audio_level = 120; + voice_receiver_info->expand_rate = 121; +} + class StatsCollectorTest : public testing::Test { protected: StatsCollectorTest() @@ -211,8 +438,7 @@ class StatsCollectorTest : public testing::Test { new cricket::ChannelManager(media_engine_, new cricket::FakeDeviceManager(), talk_base::Thread::Current())), - session_(channel_manager_.get()), - track_id_(kTrackId) { + session_(channel_manager_.get()) { // By default, we ignore session GetStats calls. EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false)); } @@ -232,14 +458,56 @@ class StatsCollectorTest : public testing::Test { session_stats_.proxy_to_transport[vc_name] = kTransportName; } - // Adds a track with a given SSRC into the stats. - void AddVideoTrackStats() { + // Adds a outgoing video track with a given SSRC into the stats. + void AddOutgoingVideoTrackStats() { stream_ = webrtc::MediaStream::Create("streamlabel"); - track_= webrtc::VideoTrack::Create(kTrackId, NULL); + track_= webrtc::VideoTrack::Create(kLocalTrackId, NULL); stream_->AddTrack(track_); - EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _)) - .WillRepeatedly(DoAll(SetArgPointee<1>(track_id_), - Return(true))); + EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); + EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(Return(false)); + } + + // Adds a incoming video track with a given SSRC into the stats. + void AddIncomingVideoTrackStats() { + stream_ = webrtc::MediaStream::Create("streamlabel"); + track_= webrtc::VideoTrack::Create(kRemoteTrackId, NULL); + stream_->AddTrack(track_); + EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), + Return(true))); + } + + // Adds a outgoing audio track with a given SSRC into the stats. + void AddOutgoingAudioTrackStats() { + if (stream_ == NULL) + stream_ = webrtc::MediaStream::Create("streamlabel"); + + audio_track_ = new talk_base::RefCountedObject<FakeAudioTrack>( + kLocalTrackId); + stream_->AddTrack(audio_track_); + EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(kLocalTrackId), + Return(true))); + EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(Return(false)); + } + + // Adds a incoming audio track with a given SSRC into the stats. + void AddIncomingAudioTrackStats() { + if (stream_ == NULL) + stream_ = webrtc::MediaStream::Create("streamlabel"); + + audio_track_ = new talk_base::RefCountedObject<FakeAudioTrack>( + kRemoteTrackId); + stream_->AddTrack(audio_track_); + EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); } void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert, @@ -247,7 +515,7 @@ class StatsCollectorTest : public testing::Test { const talk_base::FakeSSLCertificate& remote_cert, const std::vector<std::string>& remote_ders) { webrtc::StatsCollector stats; // Implementation under test. - webrtc::StatsReports reports; // returned values. + StatsReports reports; // returned values. stats.set_session(&session_); // Fake stats to process. @@ -286,32 +554,40 @@ class StatsCollectorTest : public testing::Test { EXPECT_CALL(session_, GetStats(_)) .WillOnce(DoAll(SetArgPointee<0>(session_stats), Return(true))); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); - const webrtc::StatsReport* channel_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeComponent, 1); + const StatsReport* channel_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeComponent, 1); EXPECT_TRUE(channel_report != NULL); // Check local certificate chain. std::string local_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameLocalCertificateId); - EXPECT_NE(kNotFound, local_certificate_id); - CheckCertChainReports(reports, local_ders, local_certificate_id); + StatsReport::kStatsValueNameLocalCertificateId); + if (local_ders.size() > 0) { + EXPECT_NE(kNotFound, local_certificate_id); + CheckCertChainReports(reports, local_ders, local_certificate_id); + } else { + EXPECT_EQ(kNotFound, local_certificate_id); + } // Check remote certificate chain. std::string remote_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameRemoteCertificateId); - EXPECT_NE(kNotFound, remote_certificate_id); - CheckCertChainReports(reports, remote_ders, remote_certificate_id); + StatsReport::kStatsValueNameRemoteCertificateId); + if (remote_ders.size() > 0) { + EXPECT_NE(kNotFound, remote_certificate_id); + CheckCertChainReports(reports, remote_ders, remote_certificate_id); + } else { + EXPECT_EQ(kNotFound, remote_certificate_id); + } } cricket::FakeMediaEngine* media_engine_; @@ -320,16 +596,16 @@ class StatsCollectorTest : public testing::Test { cricket::SessionStats session_stats_; talk_base::scoped_refptr<webrtc::MediaStream> stream_; talk_base::scoped_refptr<webrtc::VideoTrack> track_; - std::string track_id_; + talk_base::scoped_refptr<FakeAudioTrack> audio_track_; }; // This test verifies that 64-bit counters are passed successfully. TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, "", false, NULL); - webrtc::StatsReports reports; // returned values. + 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. @@ -337,7 +613,7 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { const std::string kBytesSentString("12345678901234"); stats.set_session(&session_); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); // Construct a stats value to read. @@ -345,12 +621,12 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { video_sender_info.bytes_sent = kBytesSent; stats_read.senders.push_back(video_sender_info); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillOnce(DoAll(SetArgPointee<1>(stats_read), Return(true))); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); std::string result = ExtractSsrcStatsValue(reports, "bytesSent"); EXPECT_EQ(kBytesSentString, result); @@ -359,10 +635,10 @@ TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { // Test that BWE information is reported via stats. TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, "", false, NULL); - webrtc::StatsReports reports; // returned values. + 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 @@ -371,7 +647,7 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { const std::string kBytesSentString("12345678901234"); stats.set_session(&session_); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); // Construct a stats value to read. @@ -384,13 +660,13 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { bwe.target_enc_bitrate = kTargetEncBitrate; stats_read.bw_estimations.push_back(bwe); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillOnce(DoAll(SetArgPointee<1>(stats_read), Return(true))); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); std::string result = ExtractSsrcStatsValue(reports, "bytesSent"); EXPECT_EQ(kBytesSentString, result); @@ -402,14 +678,14 @@ TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { // exists in the returned stats. TEST_F(StatsCollectorTest, SessionObjectExists) { webrtc::StatsCollector stats; // Implementation under test. - webrtc::StatsReports reports; // returned values. + StatsReports reports; // returned values. stats.set_session(&session_); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); - stats.UpdateStats(); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); - const webrtc::StatsReport* session_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeSession, 1); + const StatsReport* session_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeSession, 1); EXPECT_FALSE(session_report == NULL); } @@ -417,18 +693,18 @@ TEST_F(StatsCollectorTest, SessionObjectExists) { // in the returned stats. TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { webrtc::StatsCollector stats; // Implementation under test. - webrtc::StatsReports reports; // returned values. + StatsReports reports; // returned values. stats.set_session(&session_); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); - stats.UpdateStats(); - stats.UpdateStats(); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); - const webrtc::StatsReport* session_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeSession, 1); + const StatsReport* session_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeSession, 1); EXPECT_FALSE(session_report == NULL); session_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeSession, 2); + reports, StatsReport::kStatsReportTypeSession, 2); EXPECT_EQ(NULL, session_report); } @@ -436,42 +712,42 @@ TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { // without calling StatsCollector::UpdateStats. TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, "", false, NULL); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); stats.set_session(&session_); - webrtc::StatsReports reports; + StatsReports reports; // Verfies the existence of the track report. stats.GetStats(NULL, &reports); EXPECT_EQ((size_t)1, reports.size()); - EXPECT_EQ(std::string(webrtc::StatsReport::kStatsReportTypeTrack), + EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack), reports[0].type); std::string trackValue = - ExtractStatsValue(webrtc::StatsReport::kStatsReportTypeTrack, + ExtractStatsValue(StatsReport::kStatsReportTypeTrack, reports, - webrtc::StatsReport::kStatsValueNameTrackId); - EXPECT_EQ(kTrackId, trackValue); + StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, trackValue); } // This test verifies that the empty track report exists in the returned stats // when StatsCollector::UpdateStats is called with ssrc stats. TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, "", false, NULL); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); stats.set_session(&session_); - webrtc::StatsReports reports; + StatsReports reports; // Constructs an ssrc stats update. cricket::VideoSenderInfo video_sender_info; @@ -483,53 +759,54 @@ TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { video_sender_info.bytes_sent = kBytesSent; stats_read.senders.push_back(video_sender_info); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillOnce(DoAll(SetArgPointee<0>(stats_read), + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillOnce(DoAll(SetArgPointee<1>(stats_read), Return(true))); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); // |reports| should contain at least one session report, one track report, // and one ssrc report. EXPECT_LE((size_t)3, reports.size()); - const webrtc::StatsReport* track_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeTrack, 1); - EXPECT_FALSE(track_report == NULL); + const StatsReport* track_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeTrack, 1); + EXPECT_TRUE(track_report); + // Get report for the specific |track|. 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()); track_report = FindNthReportByType( - reports, webrtc::StatsReport::kStatsReportTypeTrack, 1); - EXPECT_FALSE(track_report == NULL); + reports, StatsReport::kStatsReportTypeTrack, 1); + EXPECT_TRUE(track_report); std::string ssrc_id = ExtractSsrcStatsValue( - reports, webrtc::StatsReport::kStatsValueNameSsrc); + reports, StatsReport::kStatsValueNameSsrc); EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id); std::string track_id = ExtractSsrcStatsValue( - reports, webrtc::StatsReport::kStatsValueNameTrackId); - EXPECT_EQ(kTrackId, track_id); + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, track_id); } // 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_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); // The content_name known by the video channel. const std::string kVcName("vcname"); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, kVcName, false, NULL); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); stats.set_session(&session_); - webrtc::StatsReports reports; + StatsReports reports; // Constructs an ssrc stats update. cricket::VideoSenderInfo video_sender_info; @@ -541,26 +818,26 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { video_sender_info.bytes_sent = kBytesSent; stats_read.senders.push_back(video_sender_info); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read), Return(true))); InitSessionStats(kVcName); EXPECT_CALL(session_, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), - Return(true))); + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); std::string transport_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeSsrc, + StatsReport::kStatsReportTypeSsrc, reports, - webrtc::StatsReport::kStatsValueNameTransportId); + StatsReport::kStatsValueNameTransportId); ASSERT_NE(kNotFound, transport_id); - const webrtc::StatsReport* transport_report = FindReportById(reports, - transport_id); + const StatsReport* transport_report = FindReportById(reports, + transport_id); ASSERT_FALSE(transport_report == NULL); } @@ -568,24 +845,24 @@ TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { // an outgoing SSRC where remote stats are not returned. TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); // The content_name known by the video channel. const std::string kVcName("vcname"); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, kVcName, false, NULL); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); stats.set_session(&session_); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); - stats.UpdateStats(); - webrtc::StatsReports reports; + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + StatsReports reports; stats.GetStats(NULL, &reports); - const webrtc::StatsReport* remote_report = FindNthReportByType(reports, - webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1); + const StatsReport* remote_report = FindNthReportByType(reports, + StatsReport::kStatsReportTypeRemoteSsrc, 1); EXPECT_TRUE(remote_report == NULL); } @@ -593,23 +870,23 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { // an outgoing SSRC where stats are returned. TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { webrtc::StatsCollector stats; // Implementation under test. - MockVideoMediaChannel* media_channel = new MockVideoMediaChannel; + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); // The content_name known by the video channel. const std::string kVcName("vcname"); cricket::VideoChannel video_channel(talk_base::Thread::Current(), media_engine_, media_channel, &session_, kVcName, false, NULL); - AddVideoTrackStats(); + AddOutgoingVideoTrackStats(); stats.AddStream(stream_); stats.set_session(&session_); - webrtc::StatsReports reports; + StatsReports reports; // Instruct the session to return stats containing the transport channel. InitSessionStats(kVcName); EXPECT_CALL(session_, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), - Return(true))); + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); // Constructs an ssrc stats update. cricket::VideoMediaInfo stats_read; @@ -622,20 +899,69 @@ TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { video_sender_info.remote_stats.push_back(remote_ssrc_stats); stats_read.senders.push_back(video_sender_info); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(Return(&video_channel)); - EXPECT_CALL(*media_channel, GetStats(_)) - .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read), Return(true))); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); - const webrtc::StatsReport* remote_report = FindNthReportByType(reports, - webrtc::StatsReport::kStatsReportTypeRemoteSsrc, 1); + + const StatsReport* remote_report = FindNthReportByType(reports, + StatsReport::kStatsReportTypeRemoteSsrc, 1); EXPECT_FALSE(remote_report == NULL); EXPECT_NE(0, 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_F(StatsCollectorTest, ReportsFromRemoteTrack) { + webrtc::StatsCollector stats; // Implementation under test. + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); + cricket::VideoChannel video_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, "", false, NULL); + AddIncomingVideoTrackStats(); + stats.AddStream(stream_); + + stats.set_session(&session_); + + StatsReports reports; + + // Constructs an ssrc stats update. + cricket::VideoReceiverInfo video_receiver_info; + cricket::VideoMediaInfo stats_read; + const int64 kNumOfPacketsConcealed = 54321; + + // Construct a stats value to read. + video_receiver_info.add_ssrc(1234); + video_receiver_info.packets_concealed = kNumOfPacketsConcealed; + stats_read.receivers.push_back(video_receiver_info); + + EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_, _)) + .WillOnce(DoAll(SetArgPointee<1>(stats_read), + Return(true))); + + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats.GetStats(NULL, &reports); + // |reports| should contain at least one session report, one track report, + // and one ssrc report. + EXPECT_LE(static_cast<size_t>(3), reports.size()); + const StatsReport* track_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeTrack, 1); + EXPECT_TRUE(track_report); + + std::string ssrc_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameSsrc); + EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id); + + std::string track_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kRemoteTrackId, track_id); +} + // This test verifies that all chained certificates are correctly // reported TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { @@ -678,7 +1004,7 @@ TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { // transport is present. TEST_F(StatsCollectorTest, NoTransport) { webrtc::StatsCollector stats; // Implementation under test. - webrtc::StatsReports reports; // returned values. + StatsReports reports; // returned values. stats.set_session(&session_); // Fake stats to process. @@ -700,24 +1026,24 @@ TEST_F(StatsCollectorTest, NoTransport) { .WillOnce(DoAll(SetArgPointee<0>(session_stats), Return(true))); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); // Check that the local certificate is absent. std::string local_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameLocalCertificateId); + StatsReport::kStatsValueNameLocalCertificateId); ASSERT_EQ(kNotFound, local_certificate_id); // Check that the remote certificate is absent. std::string remote_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameRemoteCertificateId); + StatsReport::kStatsValueNameRemoteCertificateId); ASSERT_EQ(kNotFound, remote_certificate_id); } @@ -725,7 +1051,7 @@ TEST_F(StatsCollectorTest, NoTransport) { // does not have any certificates. TEST_F(StatsCollectorTest, NoCertificates) { webrtc::StatsCollector stats; // Implementation under test. - webrtc::StatsReports reports; // returned values. + StatsReports reports; // returned values. stats.set_session(&session_); // Fake stats to process. @@ -753,25 +1079,343 @@ TEST_F(StatsCollectorTest, NoCertificates) { EXPECT_CALL(session_, GetStats(_)) .WillOnce(DoAll(SetArgPointee<0>(session_stats), Return(true))); - EXPECT_CALL(session_, video_channel()) - .WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); - stats.UpdateStats(); + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); stats.GetStats(NULL, &reports); // Check that the local certificate is absent. std::string local_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameLocalCertificateId); + StatsReport::kStatsValueNameLocalCertificateId); ASSERT_EQ(kNotFound, local_certificate_id); // Check that the remote certificate is absent. std::string remote_certificate_id = ExtractStatsValue( - webrtc::StatsReport::kStatsReportTypeComponent, + StatsReport::kStatsReportTypeComponent, reports, - webrtc::StatsReport::kStatsValueNameRemoteCertificateId); + 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) { + // Build a local certificate. + std::string local_der = "This is the local der."; + talk_base::FakeSSLCertificate local_cert(DerToPem(local_der)); + + // Build a remote certificate with an unsupported digest algorithm. + std::string remote_der = "This is somebody else's der."; + talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der)); + remote_cert.set_digest_algorithm("foobar"); + + TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), + remote_cert, std::vector<std::string>()); +} + +// Verifies the correct optons are passed to the VideoMediaChannel when using +// verbose output level. +TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) { + webrtc::StatsCollector stats; // Implementation under test. + MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); + cricket::VideoChannel video_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, "", false, NULL); + stats.set_session(&session_); + + StatsReports reports; // returned values. + cricket::VideoMediaInfo stats_read; + cricket::BandwidthEstimationInfo bwe; + bwe.total_received_propagation_delta_ms = 10; + bwe.recent_received_propagation_delta_ms.push_back(100); + bwe.recent_received_propagation_delta_ms.push_back(200); + bwe.recent_received_packet_group_arrival_time_ms.push_back(1000); + bwe.recent_received_packet_group_arrival_time_ms.push_back(2000); + stats_read.bw_estimations.push_back(bwe); + + EXPECT_CALL(session_, video_channel()) + .WillRepeatedly(Return(&video_channel)); + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); + + StatsOptions options; + options.include_received_propagation_stats = true; + EXPECT_CALL(*media_channel, GetStats( + Field(&StatsOptions::include_received_propagation_stats, true), + _)) + .WillOnce(DoAll(SetArgPointee<1>(stats_read), + Return(true))); + + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelDebug); + stats.GetStats(NULL, &reports); + std::string result = ExtractBweStatsValue( + reports, "googReceivedPacketGroupPropagationDeltaSumDebug"); + EXPECT_EQ("10", result); + result = ExtractBweStatsValue( + reports, "googReceivedPacketGroupPropagationDeltaDebug"); + EXPECT_EQ("[100, 200]", result); + result = ExtractBweStatsValue( + reports, "googReceivedPacketGroupArrivalTimeDebug"); + EXPECT_EQ("[1000, 2000]", result); +} + +// This test verifies that a local stats object can get statistics via +// AudioTrackInterface::GetStats() method. +TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) { + webrtc::StatsCollector stats; // Implementation under test. + MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); + // The content_name known by the voice channel. + const std::string kVcName("vcname"); + cricket::VoiceChannel voice_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, kVcName, false); + AddOutgoingAudioTrackStats(); + stats.AddStream(stream_); + stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + + stats.set_session(&session_); + + // Instruct the session to return stats containing the transport channel. + InitSessionStats(kVcName); + EXPECT_CALL(session_, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); + + cricket::VoiceSenderInfo voice_sender_info; + InitVoiceSenderInfo(&voice_sender_info); + + // Constructs an ssrc stats update. + cricket::VoiceMediaInfo stats_read; + stats_read.senders.push_back(voice_sender_info); + + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + Return(true))); + + StatsReports reports; // returned values. + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats.GetStats(NULL, &reports); + + // Verfy the existence of the track report. + const StatsReport* report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeSsrc, 1); + EXPECT_FALSE(report == NULL); + std::string track_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, track_id); + std::string ssrc_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameSsrc); + EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id); + + // Verifies the values in the track report. + UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info); + VerifyVoiceSenderInfoReport(report, voice_sender_info); + + // Verify we get the same result by passing a track to GetStats(). + StatsReports track_reports; // returned values. + stats.GetStats(audio_track_.get(), &track_reports); + const StatsReport* track_report = FindNthReportByType( + track_reports, StatsReport::kStatsReportTypeSsrc, 1); + EXPECT_TRUE(track_report); + track_id = ExtractSsrcStatsValue(track_reports, + StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, track_id); + ssrc_id = ExtractSsrcStatsValue(track_reports, + StatsReport::kStatsValueNameSsrc); + EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id); + VerifyVoiceSenderInfoReport(track_report, voice_sender_info); + + // Verify that there is no remote report for the local audio track because + // we did not set it up. + const StatsReport* remote_report = FindNthReportByType(reports, + StatsReport::kStatsReportTypeRemoteSsrc, 1); + EXPECT_TRUE(remote_report == NULL); +} + +// This test verifies that audio receive streams populate stats reports +// correctly. +TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { + webrtc::StatsCollector stats; // Implementation under test. + MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); + // The content_name known by the voice channel. + const std::string kVcName("vcname"); + cricket::VoiceChannel voice_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, kVcName, false); + AddIncomingAudioTrackStats(); + stats.AddStream(stream_); + + stats.set_session(&session_); + + // Instruct the session to return stats containing the transport channel. + InitSessionStats(kVcName); + EXPECT_CALL(session_, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); + + cricket::VoiceReceiverInfo voice_receiver_info; + InitVoiceReceiverInfo(&voice_receiver_info); + voice_receiver_info.codec_name = "fake_codec"; + + // Constructs an ssrc stats update. + cricket::VoiceMediaInfo stats_read; + stats_read.receivers.push_back(voice_receiver_info); + + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + Return(true))); + + StatsReports reports; // returned values. + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats.GetStats(NULL, &reports); + + // Verify the track id is |kRemoteTrackId|. + const std::string track_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kRemoteTrackId, track_id); + + // Verify the report for this remote track. + const StatsReport* report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeSsrc, 1); + EXPECT_FALSE(report == NULL); + VerifyVoiceReceiverInfoReport(report, voice_receiver_info); +} + +// This test verifies that a local stats object won't update its statistics +// after a RemoveLocalAudioTrack() call. +TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) { + webrtc::StatsCollector stats; // Implementation under test. + MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); + // The content_name known by the voice channel. + const std::string kVcName("vcname"); + cricket::VoiceChannel voice_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, kVcName, false); + AddOutgoingAudioTrackStats(); + stats.AddStream(stream_); + stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + + stats.set_session(&session_); + + // Instruct the session to return stats containing the transport channel. + InitSessionStats(kVcName); + EXPECT_CALL(session_, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); + + stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + cricket::VoiceSenderInfo voice_sender_info; + InitVoiceSenderInfo(&voice_sender_info); + + // Constructs an ssrc stats update. + cricket::VoiceMediaInfo stats_read; + stats_read.senders.push_back(voice_sender_info); + + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + Return(true))); + + StatsReports reports; // returned values. + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + stats.GetStats(NULL, &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); + std::string track_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, track_id); + std::string ssrc_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameSsrc); + EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id); + + // Verifies the values in the track report, no value will be changed by the + // AudioTrackInterface::GetSignalValue() and + // AudioProcessorInterface::AudioProcessorStats::GetStats(); + VerifyVoiceSenderInfoReport(report, voice_sender_info); +} + +// This test verifies that when ongoing and incoming audio tracks are using +// the same ssrc, they populate stats reports correctly. +TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { + webrtc::StatsCollector stats; // Implementation under test. + MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); + // The content_name known by the voice channel. + const std::string kVcName("vcname"); + cricket::VoiceChannel voice_channel(talk_base::Thread::Current(), + media_engine_, media_channel, &session_, kVcName, false); + + // Create a local stream with a local audio track and adds it to the stats. + AddOutgoingAudioTrackStats(); + stats.AddStream(stream_); + stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); + + // Create a remote stream with a remote audio track and adds it to the stats. + talk_base::scoped_refptr<webrtc::MediaStream> remote_stream( + webrtc::MediaStream::Create("remotestreamlabel")); + talk_base::scoped_refptr<FakeAudioTrack> remote_track( + new talk_base::RefCountedObject<FakeAudioTrack>(kRemoteTrackId)); + EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) + .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); + remote_stream->AddTrack(remote_track); + stats.AddStream(remote_stream); + + stats.set_session(&session_); + + // Instruct the session to return stats containing the transport channel. + InitSessionStats(kVcName); + EXPECT_CALL(session_, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), + Return(true))); + + cricket::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); + + cricket::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); + + EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); + EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); + EXPECT_CALL(*media_channel, GetStats(_)) + .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), + Return(true))); + + StatsReports reports; // returned values. + stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); + + // Get stats for the local track. + stats.GetStats(audio_track_.get(), &reports); + const StatsReport* track_report = FindNthReportByType( + reports, StatsReport::kStatsReportTypeSsrc, 1); + EXPECT_TRUE(track_report); + std::string track_id = ExtractSsrcStatsValue( + reports, StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kLocalTrackId, track_id); + VerifyVoiceSenderInfoReport(track_report, voice_sender_info); + + // Get stats for the remote track. + stats.GetStats(remote_track.get(), &reports); + track_report = FindNthReportByType(reports, + StatsReport::kStatsReportTypeSsrc, 1); + EXPECT_TRUE(track_report); + track_id = ExtractSsrcStatsValue(reports, + StatsReport::kStatsValueNameTrackId); + EXPECT_EQ(kRemoteTrackId, track_id); + VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info); +} + } // namespace |