1/* 2 * libjingle 3 * Copyright 2014 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <stdio.h> 29 30#include <algorithm> 31 32#include "talk/app/webrtc/statscollector.h" 33 34#include "talk/app/webrtc/peerconnection.h" 35#include "talk/app/webrtc/peerconnectionfactory.h" 36#include "talk/app/webrtc/mediastream.h" 37#include "talk/app/webrtc/mediastreaminterface.h" 38#include "talk/app/webrtc/mediastreamtrack.h" 39#include "talk/app/webrtc/test/fakedatachannelprovider.h" 40#include "talk/app/webrtc/videotrack.h" 41#include "talk/media/base/fakemediaengine.h" 42#include "talk/session/media/channelmanager.h" 43#include "testing/gmock/include/gmock/gmock.h" 44#include "testing/gtest/include/gtest/gtest.h" 45#include "webrtc/base/base64.h" 46#include "webrtc/base/fakesslidentity.h" 47#include "webrtc/base/gunit.h" 48#include "webrtc/base/network.h" 49#include "webrtc/p2p/base/faketransportcontroller.h" 50 51using rtc::scoped_ptr; 52using testing::_; 53using testing::DoAll; 54using testing::Field; 55using testing::Return; 56using testing::ReturnNull; 57using testing::ReturnRef; 58using testing::SetArgPointee; 59using webrtc::PeerConnectionInterface; 60using webrtc::StatsReport; 61using webrtc::StatsReports; 62 63namespace { 64// This value comes from openssl/tls1.h 65const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014; 66} // namespace 67 68namespace cricket { 69 70class ChannelManager; 71 72} // namespace cricket 73 74namespace webrtc { 75 76// Error return values 77const char kNotFound[] = "NOT FOUND"; 78 79// Constant names for track identification. 80const char kLocalTrackId[] = "local_track_id"; 81const char kRemoteTrackId[] = "remote_track_id"; 82const uint32_t kSsrcOfTrack = 1234; 83 84class MockWebRtcSession : public webrtc::WebRtcSession { 85 public: 86 explicit MockWebRtcSession(webrtc::MediaControllerInterface* media_controller) 87 : WebRtcSession(media_controller, 88 rtc::Thread::Current(), 89 rtc::Thread::Current(), 90 nullptr) {} 91 MOCK_METHOD0(voice_channel, cricket::VoiceChannel*()); 92 MOCK_METHOD0(video_channel, cricket::VideoChannel*()); 93 // Libjingle uses "local" for a outgoing track, and "remote" for a incoming 94 // track. 95 MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*)); 96 MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*)); 97 MOCK_METHOD1(GetTransportStats, bool(SessionStats*)); 98 MOCK_METHOD2(GetLocalCertificate, 99 bool(const std::string& transport_name, 100 rtc::scoped_refptr<rtc::RTCCertificate>* certificate)); 101 MOCK_METHOD2(GetRemoteSSLCertificate, 102 bool(const std::string& transport_name, 103 rtc::SSLCertificate** cert)); 104}; 105 106// The factory isn't really used; it just satisfies the base PeerConnection. 107class FakePeerConnectionFactory 108 : public rtc::RefCountedObject<PeerConnectionFactory> {}; 109 110class MockPeerConnection 111 : public rtc::RefCountedObject<webrtc::PeerConnection> { 112 public: 113 MockPeerConnection() 114 : rtc::RefCountedObject<webrtc::PeerConnection>( 115 new FakePeerConnectionFactory()) {} 116 MOCK_METHOD0(session, WebRtcSession*()); 117 MOCK_CONST_METHOD0(sctp_data_channels, 118 const std::vector<rtc::scoped_refptr<DataChannel>>&()); 119}; 120 121class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel { 122 public: 123 MockVideoMediaChannel() : 124 cricket::FakeVideoMediaChannel(NULL, cricket::VideoOptions()) {} 125 MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*)); 126}; 127 128class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel { 129 public: 130 MockVoiceMediaChannel() : 131 cricket::FakeVoiceMediaChannel(NULL, cricket::AudioOptions()) {} 132 MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*)); 133}; 134 135class FakeAudioProcessor : public webrtc::AudioProcessorInterface { 136 public: 137 FakeAudioProcessor() {} 138 ~FakeAudioProcessor() {} 139 140 private: 141 void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override { 142 stats->typing_noise_detected = true; 143 stats->echo_return_loss = 2; 144 stats->echo_return_loss_enhancement = 3; 145 stats->echo_delay_median_ms = 4; 146 stats->aec_quality_min = 5.1f; 147 stats->echo_delay_std_ms = 6; 148 } 149}; 150 151class FakeAudioTrack 152 : public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface> { 153 public: 154 explicit FakeAudioTrack(const std::string& id) 155 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id), 156 processor_(new rtc::RefCountedObject<FakeAudioProcessor>()) {} 157 std::string kind() const override { return "audio"; } 158 webrtc::AudioSourceInterface* GetSource() const override { return NULL; } 159 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} 160 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} 161 bool GetSignalLevel(int* level) override { 162 *level = 1; 163 return true; 164 } 165 rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor() 166 override { 167 return processor_; 168 } 169 170 private: 171 rtc::scoped_refptr<FakeAudioProcessor> processor_; 172}; 173 174bool GetValue(const StatsReport* report, 175 StatsReport::StatsValueName name, 176 std::string* value) { 177 const StatsReport::Value* v = report->FindValue(name); 178 if (!v) 179 return false; 180 *value = v->ToString(); 181 return true; 182} 183 184std::string ExtractStatsValue(const StatsReport::StatsType& type, 185 const StatsReports& reports, 186 StatsReport::StatsValueName name) { 187 for (const auto* r : reports) { 188 std::string ret; 189 if (r->type() == type && GetValue(r, name, &ret)) 190 return ret; 191 } 192 193 return kNotFound; 194} 195 196StatsReport::Id TypedIdFromIdString(StatsReport::StatsType type, 197 const std::string& value) { 198 EXPECT_FALSE(value.empty()); 199 StatsReport::Id id; 200 if (value.empty()) 201 return id; 202 203 // This has assumptions about how the ID is constructed. As is, this is 204 // OK since this is for testing purposes only, but if we ever need this 205 // in production, we should add a generic method that does this. 206 size_t index = value.find('_'); 207 EXPECT_NE(index, std::string::npos); 208 if (index == std::string::npos || index == (value.length() - 1)) 209 return id; 210 211 id = StatsReport::NewTypedId(type, value.substr(index + 1)); 212 EXPECT_EQ(id->ToString(), value); 213 return id; 214} 215 216StatsReport::Id IdFromCertIdString(const std::string& cert_id) { 217 return TypedIdFromIdString(StatsReport::kStatsReportTypeCertificate, cert_id); 218} 219 220// Finds the |n|-th report of type |type| in |reports|. 221// |n| starts from 1 for finding the first report. 222const StatsReport* FindNthReportByType( 223 const StatsReports& reports, const StatsReport::StatsType& type, int n) { 224 for (size_t i = 0; i < reports.size(); ++i) { 225 if (reports[i]->type() == type) { 226 n--; 227 if (n == 0) 228 return reports[i]; 229 } 230 } 231 return nullptr; 232} 233 234const StatsReport* FindReportById(const StatsReports& reports, 235 const StatsReport::Id& id) { 236 for (const auto* r : reports) { 237 if (r->id()->Equals(id)) 238 return r; 239 } 240 return nullptr; 241} 242 243std::string ExtractSsrcStatsValue(StatsReports reports, 244 StatsReport::StatsValueName name) { 245 return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name); 246} 247 248std::string ExtractBweStatsValue(StatsReports reports, 249 StatsReport::StatsValueName name) { 250 return ExtractStatsValue( 251 StatsReport::kStatsReportTypeBwe, reports, name); 252} 253 254std::string DerToPem(const std::string& der) { 255 return rtc::SSLIdentity::DerToPem( 256 rtc::kPemTypeCertificate, 257 reinterpret_cast<const unsigned char*>(der.c_str()), 258 der.length()); 259} 260 261std::vector<std::string> DersToPems( 262 const std::vector<std::string>& ders) { 263 std::vector<std::string> pems(ders.size()); 264 std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem); 265 return pems; 266} 267 268void CheckCertChainReports(const StatsReports& reports, 269 const std::vector<std::string>& ders, 270 const StatsReport::Id& start_id) { 271 StatsReport::Id cert_id; 272 const StatsReport::Id* certificate_id = &start_id; 273 size_t i = 0; 274 while (true) { 275 const StatsReport* report = FindReportById(reports, *certificate_id); 276 ASSERT_TRUE(report != NULL); 277 278 std::string der_base64; 279 EXPECT_TRUE(GetValue( 280 report, StatsReport::kStatsValueNameDer, &der_base64)); 281 std::string der = rtc::Base64::Decode(der_base64, rtc::Base64::DO_STRICT); 282 EXPECT_EQ(ders[i], der); 283 284 std::string fingerprint_algorithm; 285 EXPECT_TRUE(GetValue( 286 report, 287 StatsReport::kStatsValueNameFingerprintAlgorithm, 288 &fingerprint_algorithm)); 289 // The digest algorithm for a FakeSSLCertificate is always SHA-1. 290 std::string sha_1_str = rtc::DIGEST_SHA_1; 291 EXPECT_EQ(sha_1_str, fingerprint_algorithm); 292 293 std::string fingerprint; 294 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameFingerprint, 295 &fingerprint)); 296 EXPECT_FALSE(fingerprint.empty()); 297 298 ++i; 299 std::string issuer_id; 300 if (!GetValue(report, StatsReport::kStatsValueNameIssuerId, 301 &issuer_id)) { 302 break; 303 } 304 305 cert_id = IdFromCertIdString(issuer_id); 306 certificate_id = &cert_id; 307 } 308 EXPECT_EQ(ders.size(), i); 309} 310 311void VerifyVoiceReceiverInfoReport( 312 const StatsReport* report, 313 const cricket::VoiceReceiverInfo& info) { 314 std::string value_in_report; 315 EXPECT_TRUE(GetValue( 316 report, StatsReport::kStatsValueNameAudioOutputLevel, &value_in_report)); 317 EXPECT_EQ(rtc::ToString<int>(info.audio_level), value_in_report); 318 EXPECT_TRUE(GetValue( 319 report, StatsReport::kStatsValueNameBytesReceived, &value_in_report)); 320 EXPECT_EQ(rtc::ToString<int64_t>(info.bytes_rcvd), value_in_report); 321 EXPECT_TRUE(GetValue( 322 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); 323 EXPECT_EQ(rtc::ToString<int>(info.jitter_ms), value_in_report); 324 EXPECT_TRUE(GetValue( 325 report, StatsReport::kStatsValueNameJitterBufferMs, &value_in_report)); 326 EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_ms), value_in_report); 327 EXPECT_TRUE(GetValue( 328 report, StatsReport::kStatsValueNamePreferredJitterBufferMs, 329 &value_in_report)); 330 EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_preferred_ms), 331 value_in_report); 332 EXPECT_TRUE(GetValue( 333 report, StatsReport::kStatsValueNameCurrentDelayMs, &value_in_report)); 334 EXPECT_EQ(rtc::ToString<int>(info.delay_estimate_ms), value_in_report); 335 EXPECT_TRUE(GetValue( 336 report, StatsReport::kStatsValueNameExpandRate, &value_in_report)); 337 EXPECT_EQ(rtc::ToString<float>(info.expand_rate), value_in_report); 338 EXPECT_TRUE(GetValue( 339 report, StatsReport::kStatsValueNameSpeechExpandRate, &value_in_report)); 340 EXPECT_EQ(rtc::ToString<float>(info.speech_expand_rate), value_in_report); 341 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate, 342 &value_in_report)); 343 EXPECT_EQ(rtc::ToString<float>(info.accelerate_rate), value_in_report); 344 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate, 345 &value_in_report)); 346 EXPECT_EQ(rtc::ToString<float>(info.preemptive_expand_rate), value_in_report); 347 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate, 348 &value_in_report)); 349 EXPECT_EQ(rtc::ToString<float>(info.secondary_decoded_rate), value_in_report); 350 EXPECT_TRUE(GetValue( 351 report, StatsReport::kStatsValueNamePacketsReceived, &value_in_report)); 352 EXPECT_EQ(rtc::ToString<int>(info.packets_rcvd), value_in_report); 353 EXPECT_TRUE(GetValue( 354 report, StatsReport::kStatsValueNameDecodingCTSG, &value_in_report)); 355 EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_silence_generator), 356 value_in_report); 357 EXPECT_TRUE(GetValue( 358 report, StatsReport::kStatsValueNameDecodingCTN, &value_in_report)); 359 EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_neteq), 360 value_in_report); 361 EXPECT_TRUE(GetValue( 362 report, StatsReport::kStatsValueNameDecodingNormal, &value_in_report)); 363 EXPECT_EQ(rtc::ToString<int>(info.decoding_normal), value_in_report); 364 EXPECT_TRUE(GetValue( 365 report, StatsReport::kStatsValueNameDecodingPLC, &value_in_report)); 366 EXPECT_EQ(rtc::ToString<int>(info.decoding_plc), value_in_report); 367 EXPECT_TRUE(GetValue( 368 report, StatsReport::kStatsValueNameDecodingCNG, &value_in_report)); 369 EXPECT_EQ(rtc::ToString<int>(info.decoding_cng), value_in_report); 370 EXPECT_TRUE(GetValue( 371 report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report)); 372 EXPECT_EQ(rtc::ToString<int>(info.decoding_plc_cng), value_in_report); 373 EXPECT_TRUE(GetValue( 374 report, StatsReport::kStatsValueNameCodecName, &value_in_report)); 375} 376 377 378void VerifyVoiceSenderInfoReport(const StatsReport* report, 379 const cricket::VoiceSenderInfo& sinfo) { 380 std::string value_in_report; 381 EXPECT_TRUE(GetValue( 382 report, StatsReport::kStatsValueNameCodecName, &value_in_report)); 383 EXPECT_EQ(sinfo.codec_name, value_in_report); 384 EXPECT_TRUE(GetValue( 385 report, StatsReport::kStatsValueNameBytesSent, &value_in_report)); 386 EXPECT_EQ(rtc::ToString<int64_t>(sinfo.bytes_sent), value_in_report); 387 EXPECT_TRUE(GetValue( 388 report, StatsReport::kStatsValueNamePacketsSent, &value_in_report)); 389 EXPECT_EQ(rtc::ToString<int>(sinfo.packets_sent), value_in_report); 390 EXPECT_TRUE(GetValue( 391 report, StatsReport::kStatsValueNamePacketsLost, &value_in_report)); 392 EXPECT_EQ(rtc::ToString<int>(sinfo.packets_lost), value_in_report); 393 EXPECT_TRUE(GetValue( 394 report, StatsReport::kStatsValueNameRtt, &value_in_report)); 395 EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report); 396 EXPECT_TRUE(GetValue( 397 report, StatsReport::kStatsValueNameRtt, &value_in_report)); 398 EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report); 399 EXPECT_TRUE(GetValue( 400 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); 401 EXPECT_EQ(rtc::ToString<int>(sinfo.jitter_ms), value_in_report); 402 EXPECT_TRUE(GetValue( 403 report, StatsReport::kStatsValueNameEchoCancellationQualityMin, 404 &value_in_report)); 405 EXPECT_EQ(rtc::ToString<float>(sinfo.aec_quality_min), value_in_report); 406 EXPECT_TRUE(GetValue( 407 report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report)); 408 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_delay_median_ms), 409 value_in_report); 410 EXPECT_TRUE(GetValue( 411 report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report)); 412 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_delay_std_ms), 413 value_in_report); 414 EXPECT_TRUE(GetValue( 415 report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report)); 416 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_return_loss), 417 value_in_report); 418 EXPECT_TRUE(GetValue( 419 report, StatsReport::kStatsValueNameEchoReturnLossEnhancement, 420 &value_in_report)); 421 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_return_loss_enhancement), 422 value_in_report); 423 EXPECT_TRUE(GetValue( 424 report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report)); 425 EXPECT_EQ(rtc::ToString<int>(sinfo.audio_level), value_in_report); 426 EXPECT_TRUE(GetValue( 427 report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report)); 428 std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false"; 429 EXPECT_EQ(typing_detected, value_in_report); 430} 431 432// Helper methods to avoid duplication of code. 433void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info) { 434 voice_sender_info->add_ssrc(kSsrcOfTrack); 435 voice_sender_info->codec_name = "fake_codec"; 436 voice_sender_info->bytes_sent = 100; 437 voice_sender_info->packets_sent = 101; 438 voice_sender_info->rtt_ms = 102; 439 voice_sender_info->fraction_lost = 103; 440 voice_sender_info->jitter_ms = 104; 441 voice_sender_info->packets_lost = 105; 442 voice_sender_info->ext_seqnum = 106; 443 voice_sender_info->audio_level = 107; 444 voice_sender_info->echo_return_loss = 108; 445 voice_sender_info->echo_return_loss_enhancement = 109; 446 voice_sender_info->echo_delay_median_ms = 110; 447 voice_sender_info->echo_delay_std_ms = 111; 448 voice_sender_info->aec_quality_min = 112.0f; 449 voice_sender_info->typing_noise_detected = false; 450} 451 452void UpdateVoiceSenderInfoFromAudioTrack( 453 FakeAudioTrack* audio_track, cricket::VoiceSenderInfo* voice_sender_info) { 454 audio_track->GetSignalLevel(&voice_sender_info->audio_level); 455 webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats; 456 audio_track->GetAudioProcessor()->GetStats(&audio_processor_stats); 457 voice_sender_info->typing_noise_detected = 458 audio_processor_stats.typing_noise_detected; 459 voice_sender_info->echo_return_loss = audio_processor_stats.echo_return_loss; 460 voice_sender_info->echo_return_loss_enhancement = 461 audio_processor_stats.echo_return_loss_enhancement; 462 voice_sender_info->echo_delay_median_ms = 463 audio_processor_stats.echo_delay_median_ms; 464 voice_sender_info->aec_quality_min = audio_processor_stats.aec_quality_min; 465 voice_sender_info->echo_delay_std_ms = 466 audio_processor_stats.echo_delay_std_ms; 467} 468 469void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) { 470 voice_receiver_info->add_ssrc(kSsrcOfTrack); 471 voice_receiver_info->bytes_rcvd = 110; 472 voice_receiver_info->packets_rcvd = 111; 473 voice_receiver_info->packets_lost = 112; 474 voice_receiver_info->fraction_lost = 113; 475 voice_receiver_info->packets_lost = 114; 476 voice_receiver_info->ext_seqnum = 115; 477 voice_receiver_info->jitter_ms = 116; 478 voice_receiver_info->jitter_buffer_ms = 117; 479 voice_receiver_info->jitter_buffer_preferred_ms = 118; 480 voice_receiver_info->delay_estimate_ms = 119; 481 voice_receiver_info->audio_level = 120; 482 voice_receiver_info->expand_rate = 121; 483 voice_receiver_info->speech_expand_rate = 122; 484 voice_receiver_info->secondary_decoded_rate = 123; 485 voice_receiver_info->accelerate_rate = 124; 486 voice_receiver_info->preemptive_expand_rate = 125; 487} 488 489class StatsCollectorForTest : public webrtc::StatsCollector { 490 public: 491 explicit StatsCollectorForTest(PeerConnection* pc) 492 : StatsCollector(pc), time_now_(19477) {} 493 494 double GetTimeNow() override { 495 return time_now_; 496 } 497 498 private: 499 double time_now_; 500}; 501 502class StatsCollectorTest : public testing::Test { 503 protected: 504 StatsCollectorTest() 505 : media_engine_(new cricket::FakeMediaEngine()), 506 channel_manager_( 507 new cricket::ChannelManager(media_engine_, rtc::Thread::Current())), 508 media_controller_( 509 webrtc::MediaControllerInterface::Create(rtc::Thread::Current(), 510 channel_manager_.get())), 511 session_(media_controller_.get()) { 512 // By default, we ignore session GetStats calls. 513 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false)); 514 // Add default returns for mock classes. 515 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); 516 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 517 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_)); 518 EXPECT_CALL(pc_, sctp_data_channels()) 519 .WillRepeatedly(ReturnRef(data_channels_)); 520 } 521 522 ~StatsCollectorTest() {} 523 524 // This creates a standard setup with a transport called "trspname" 525 // having one transport channel 526 // and the specified virtual connection name. 527 void InitSessionStats(const std::string& vc_name) { 528 const std::string kTransportName("trspname"); 529 cricket::TransportStats transport_stats; 530 cricket::TransportChannelStats channel_stats; 531 channel_stats.component = 1; 532 transport_stats.transport_name = kTransportName; 533 transport_stats.channel_stats.push_back(channel_stats); 534 535 session_stats_.transport_stats[kTransportName] = transport_stats; 536 session_stats_.proxy_to_transport[vc_name] = kTransportName; 537 } 538 539 // Adds a outgoing video track with a given SSRC into the stats. 540 void AddOutgoingVideoTrackStats() { 541 stream_ = webrtc::MediaStream::Create("streamlabel"); 542 track_= webrtc::VideoTrack::Create(kLocalTrackId, NULL); 543 stream_->AddTrack(track_); 544 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) 545 .WillRepeatedly(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); 546 } 547 548 // Adds a incoming video track with a given SSRC into the stats. 549 void AddIncomingVideoTrackStats() { 550 stream_ = webrtc::MediaStream::Create("streamlabel"); 551 track_= webrtc::VideoTrack::Create(kRemoteTrackId, NULL); 552 stream_->AddTrack(track_); 553 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) 554 .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); 555 } 556 557 // Adds a outgoing audio track with a given SSRC into the stats. 558 void AddOutgoingAudioTrackStats() { 559 if (stream_ == NULL) 560 stream_ = webrtc::MediaStream::Create("streamlabel"); 561 562 audio_track_ = new rtc::RefCountedObject<FakeAudioTrack>( 563 kLocalTrackId); 564 stream_->AddTrack(audio_track_); 565 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) 566 .WillOnce(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); 567 } 568 569 // Adds a incoming audio track with a given SSRC into the stats. 570 void AddIncomingAudioTrackStats() { 571 if (stream_ == NULL) 572 stream_ = webrtc::MediaStream::Create("streamlabel"); 573 574 audio_track_ = new rtc::RefCountedObject<FakeAudioTrack>( 575 kRemoteTrackId); 576 stream_->AddTrack(audio_track_); 577 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) 578 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); 579 } 580 581 void AddDataChannel(cricket::DataChannelType type, 582 const std::string& label, 583 int id) { 584 InternalDataChannelInit config; 585 config.id = id; 586 587 data_channels_.push_back(DataChannel::Create( 588 &data_channel_provider_, cricket::DCT_SCTP, label, config)); 589 } 590 591 StatsReport* AddCandidateReport(StatsCollector* collector, 592 const cricket::Candidate& candidate, 593 bool local) { 594 return collector->AddCandidateReport(candidate, local); 595 } 596 597 void SetupAndVerifyAudioTrackStats( 598 FakeAudioTrack* audio_track, 599 webrtc::MediaStream* stream, 600 webrtc::StatsCollector* stats, 601 cricket::VoiceChannel* voice_channel, 602 const std::string& vc_name, 603 MockVoiceMediaChannel* media_channel, 604 cricket::VoiceSenderInfo* voice_sender_info, 605 cricket::VoiceReceiverInfo* voice_receiver_info, 606 cricket::VoiceMediaInfo* stats_read, 607 StatsReports* reports) { 608 // A track can't have both sender report and recv report at the same time 609 // for now, this might change in the future though. 610 ASSERT((voice_sender_info == NULL) ^ (voice_receiver_info == NULL)); 611 612 // Instruct the session to return stats containing the transport channel. 613 InitSessionStats(vc_name); 614 EXPECT_CALL(session_, GetTransportStats(_)) 615 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 616 Return(true))); 617 618 // Constructs an ssrc stats update. 619 if (voice_sender_info) 620 stats_read->senders.push_back(*voice_sender_info); 621 if (voice_receiver_info) 622 stats_read->receivers.push_back(*voice_receiver_info); 623 624 EXPECT_CALL(session_, voice_channel()).WillRepeatedly( 625 Return(voice_channel)); 626 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); 627 EXPECT_CALL(*media_channel, GetStats(_)) 628 .WillOnce(DoAll(SetArgPointee<0>(*stats_read), Return(true))); 629 630 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 631 stats->ClearUpdateStatsCacheForTest(); 632 stats->GetStats(NULL, reports); 633 634 // Verify the existence of the track report. 635 const StatsReport* report = FindNthReportByType( 636 *reports, StatsReport::kStatsReportTypeSsrc, 1); 637 EXPECT_FALSE(report == NULL); 638 EXPECT_EQ(stats->GetTimeNow(), report->timestamp()); 639 std::string track_id = ExtractSsrcStatsValue( 640 *reports, StatsReport::kStatsValueNameTrackId); 641 EXPECT_EQ(audio_track->id(), track_id); 642 std::string ssrc_id = ExtractSsrcStatsValue( 643 *reports, StatsReport::kStatsValueNameSsrc); 644 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); 645 646 // Verifies the values in the track report. 647 if (voice_sender_info) { 648 UpdateVoiceSenderInfoFromAudioTrack(audio_track, voice_sender_info); 649 VerifyVoiceSenderInfoReport(report, *voice_sender_info); 650 } 651 if (voice_receiver_info) { 652 VerifyVoiceReceiverInfoReport(report, *voice_receiver_info); 653 } 654 655 // Verify we get the same result by passing a track to GetStats(). 656 StatsReports track_reports; // returned values. 657 stats->GetStats(audio_track, &track_reports); 658 const StatsReport* track_report = FindNthReportByType( 659 track_reports, StatsReport::kStatsReportTypeSsrc, 1); 660 EXPECT_TRUE(track_report); 661 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); 662 track_id = ExtractSsrcStatsValue(track_reports, 663 StatsReport::kStatsValueNameTrackId); 664 EXPECT_EQ(audio_track->id(), track_id); 665 ssrc_id = ExtractSsrcStatsValue(track_reports, 666 StatsReport::kStatsValueNameSsrc); 667 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); 668 if (voice_sender_info) 669 VerifyVoiceSenderInfoReport(track_report, *voice_sender_info); 670 if (voice_receiver_info) 671 VerifyVoiceReceiverInfoReport(track_report, *voice_receiver_info); 672 } 673 674 void TestCertificateReports(const rtc::FakeSSLCertificate& local_cert, 675 const std::vector<std::string>& local_ders, 676 const rtc::FakeSSLCertificate& remote_cert, 677 const std::vector<std::string>& remote_ders) { 678 StatsCollectorForTest stats(&pc_); 679 680 StatsReports reports; // returned values. 681 682 // Fake stats to process. 683 cricket::TransportChannelStats channel_stats; 684 channel_stats.component = 1; 685 channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; 686 channel_stats.ssl_cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; 687 688 cricket::TransportStats transport_stats; 689 transport_stats.transport_name = "audio"; 690 transport_stats.channel_stats.push_back(channel_stats); 691 692 SessionStats session_stats; 693 session_stats.transport_stats[transport_stats.transport_name] = 694 transport_stats; 695 696 // Fake certificate to report 697 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate( 698 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::FakeSSLIdentity>( 699 new rtc::FakeSSLIdentity(local_cert)))); 700 701 // Configure MockWebRtcSession 702 EXPECT_CALL(session_, 703 GetLocalCertificate(transport_stats.transport_name, _)) 704 .WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true))); 705 EXPECT_CALL(session_, 706 GetRemoteSSLCertificate(transport_stats.transport_name, _)) 707 .WillOnce( 708 DoAll(SetArgPointee<1>(remote_cert.GetReference()), Return(true))); 709 EXPECT_CALL(session_, GetTransportStats(_)) 710 .WillOnce(DoAll(SetArgPointee<0>(session_stats), 711 Return(true))); 712 713 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 714 715 stats.GetStats(NULL, &reports); 716 717 const StatsReport* channel_report = FindNthReportByType( 718 reports, StatsReport::kStatsReportTypeComponent, 1); 719 EXPECT_TRUE(channel_report != NULL); 720 721 // Check local certificate chain. 722 std::string local_certificate_id = ExtractStatsValue( 723 StatsReport::kStatsReportTypeComponent, 724 reports, 725 StatsReport::kStatsValueNameLocalCertificateId); 726 if (local_ders.size() > 0) { 727 EXPECT_NE(kNotFound, local_certificate_id); 728 StatsReport::Id id(IdFromCertIdString(local_certificate_id)); 729 CheckCertChainReports(reports, local_ders, id); 730 } else { 731 EXPECT_EQ(kNotFound, local_certificate_id); 732 } 733 734 // Check remote certificate chain. 735 std::string remote_certificate_id = ExtractStatsValue( 736 StatsReport::kStatsReportTypeComponent, 737 reports, 738 StatsReport::kStatsValueNameRemoteCertificateId); 739 if (remote_ders.size() > 0) { 740 EXPECT_NE(kNotFound, remote_certificate_id); 741 StatsReport::Id id(IdFromCertIdString(remote_certificate_id)); 742 CheckCertChainReports(reports, remote_ders, id); 743 } else { 744 EXPECT_EQ(kNotFound, remote_certificate_id); 745 } 746 747 // Check negotiated ciphers. 748 std::string dtls_cipher_suite = 749 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, 750 StatsReport::kStatsValueNameDtlsCipher); 751 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName( 752 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), 753 dtls_cipher_suite); 754 std::string srtp_crypto_suite = 755 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, 756 StatsReport::kStatsValueNameSrtpCipher); 757 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::SRTP_AES128_CM_SHA1_80), 758 srtp_crypto_suite); 759 } 760 761 cricket::FakeMediaEngine* media_engine_; 762 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; 763 rtc::scoped_ptr<webrtc::MediaControllerInterface> media_controller_; 764 MockWebRtcSession session_; 765 MockPeerConnection pc_; 766 FakeDataChannelProvider data_channel_provider_; 767 SessionStats session_stats_; 768 rtc::scoped_refptr<webrtc::MediaStream> stream_; 769 rtc::scoped_refptr<webrtc::VideoTrack> track_; 770 rtc::scoped_refptr<FakeAudioTrack> audio_track_; 771 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; 772}; 773 774// Verify that ExtractDataInfo populates reports. 775TEST_F(StatsCollectorTest, ExtractDataInfo) { 776 const std::string label = "hacks"; 777 const int id = 31337; 778 const std::string state = DataChannelInterface::DataStateString( 779 DataChannelInterface::DataState::kConnecting); 780 781 AddDataChannel(cricket::DCT_SCTP, label, id); 782 StatsCollectorForTest stats(&pc_); 783 784 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 785 786 StatsReports reports; 787 stats.GetStats(NULL, &reports); 788 789 const StatsReport* report = 790 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); 791 792 StatsReport::Id reportId = StatsReport::NewTypedIntId( 793 StatsReport::kStatsReportTypeDataChannel, id); 794 795 EXPECT_TRUE(reportId->Equals(report->id())); 796 797 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); 798 EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, 799 reports, 800 StatsReport::kStatsValueNameLabel)); 801 EXPECT_EQ(rtc::ToString<int64_t>(id), 802 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, 803 StatsReport::kStatsValueNameDataChannelId)); 804 EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, 805 reports, 806 StatsReport::kStatsValueNameState)); 807 EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, 808 reports, 809 StatsReport::kStatsValueNameProtocol)); 810} 811 812// This test verifies that 64-bit counters are passed successfully. 813TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { 814 StatsCollectorForTest stats(&pc_); 815 816 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 817 .WillRepeatedly(Return(false)); 818 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 819 .WillRepeatedly(Return(false)); 820 821 const char kVideoChannelName[] = "video"; 822 823 InitSessionStats(kVideoChannelName); 824 EXPECT_CALL(session_, GetTransportStats(_)) 825 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 826 Return(true))); 827 828 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 829 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 830 nullptr, kVideoChannelName, false); 831 StatsReports reports; // returned values. 832 cricket::VideoSenderInfo video_sender_info; 833 cricket::VideoMediaInfo stats_read; 834 // The number of bytes must be larger than 0xFFFFFFFF for this test. 835 const int64_t kBytesSent = 12345678901234LL; 836 const std::string kBytesSentString("12345678901234"); 837 838 AddOutgoingVideoTrackStats(); 839 stats.AddStream(stream_); 840 841 // Construct a stats value to read. 842 video_sender_info.add_ssrc(1234); 843 video_sender_info.bytes_sent = kBytesSent; 844 stats_read.senders.push_back(video_sender_info); 845 846 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 847 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 848 EXPECT_CALL(*media_channel, GetStats(_)) 849 .WillOnce(DoAll(SetArgPointee<0>(stats_read), 850 Return(true))); 851 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 852 stats.GetStats(NULL, &reports); 853 std::string result = ExtractSsrcStatsValue(reports, 854 StatsReport::kStatsValueNameBytesSent); 855 EXPECT_EQ(kBytesSentString, result); 856} 857 858// Test that BWE information is reported via stats. 859TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { 860 StatsCollectorForTest stats(&pc_); 861 862 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 863 .WillRepeatedly(Return(false)); 864 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 865 .WillRepeatedly(Return(false)); 866 867 const char kVideoChannelName[] = "video"; 868 869 InitSessionStats(kVideoChannelName); 870 EXPECT_CALL(session_, GetTransportStats(_)) 871 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 872 Return(true))); 873 874 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 875 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 876 nullptr, kVideoChannelName, false); 877 878 StatsReports reports; // returned values. 879 cricket::VideoSenderInfo video_sender_info; 880 cricket::VideoMediaInfo stats_read; 881 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and 882 // BWE. 883 const int64_t kBytesSent = 12345678901234LL; 884 const std::string kBytesSentString("12345678901234"); 885 886 AddOutgoingVideoTrackStats(); 887 stats.AddStream(stream_); 888 889 // Construct a stats value to read. 890 video_sender_info.add_ssrc(1234); 891 video_sender_info.bytes_sent = kBytesSent; 892 stats_read.senders.push_back(video_sender_info); 893 cricket::BandwidthEstimationInfo bwe; 894 const int kTargetEncBitrate = 123456; 895 const std::string kTargetEncBitrateString("123456"); 896 bwe.target_enc_bitrate = kTargetEncBitrate; 897 stats_read.bw_estimations.push_back(bwe); 898 899 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 900 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 901 EXPECT_CALL(*media_channel, GetStats(_)) 902 .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); 903 904 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 905 stats.GetStats(NULL, &reports); 906 std::string result = ExtractSsrcStatsValue(reports, 907 StatsReport::kStatsValueNameBytesSent); 908 EXPECT_EQ(kBytesSentString, result); 909 result = ExtractBweStatsValue(reports, 910 StatsReport::kStatsValueNameTargetEncBitrate); 911 EXPECT_EQ(kTargetEncBitrateString, result); 912} 913 914// This test verifies that an object of type "googSession" always 915// exists in the returned stats. 916TEST_F(StatsCollectorTest, SessionObjectExists) { 917 StatsCollectorForTest stats(&pc_); 918 919 StatsReports reports; // returned values. 920 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 921 stats.GetStats(NULL, &reports); 922 const StatsReport* session_report = FindNthReportByType( 923 reports, StatsReport::kStatsReportTypeSession, 1); 924 EXPECT_FALSE(session_report == NULL); 925} 926 927// This test verifies that only one object of type "googSession" exists 928// in the returned stats. 929TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { 930 StatsCollectorForTest stats(&pc_); 931 932 StatsReports reports; // returned values. 933 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 934 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 935 stats.GetStats(NULL, &reports); 936 const StatsReport* session_report = FindNthReportByType( 937 reports, StatsReport::kStatsReportTypeSession, 1); 938 EXPECT_FALSE(session_report == NULL); 939 session_report = FindNthReportByType( 940 reports, StatsReport::kStatsReportTypeSession, 2); 941 EXPECT_EQ(NULL, session_report); 942} 943 944// This test verifies that the empty track report exists in the returned stats 945// without calling StatsCollector::UpdateStats. 946TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { 947 StatsCollectorForTest stats(&pc_); 948 949 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 950 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 951 nullptr, "video", false); 952 AddOutgoingVideoTrackStats(); 953 stats.AddStream(stream_); 954 955 // Verfies the existence of the track report. 956 StatsReports reports; 957 stats.GetStats(NULL, &reports); 958 EXPECT_EQ((size_t)1, reports.size()); 959 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type()); 960 EXPECT_EQ(0, reports[0]->timestamp()); 961 962 std::string trackValue = 963 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, 964 reports, 965 StatsReport::kStatsValueNameTrackId); 966 EXPECT_EQ(kLocalTrackId, trackValue); 967} 968 969// This test verifies that the empty track report exists in the returned stats 970// when StatsCollector::UpdateStats is called with ssrc stats. 971TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { 972 StatsCollectorForTest stats(&pc_); 973 974 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 975 .WillRepeatedly(Return(false)); 976 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 977 .WillRepeatedly(Return(false)); 978 979 const char kVideoChannelName[] = "video"; 980 InitSessionStats(kVideoChannelName); 981 EXPECT_CALL(session_, GetTransportStats(_)) 982 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 983 Return(true))); 984 985 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 986 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 987 nullptr, kVideoChannelName, false); 988 AddOutgoingVideoTrackStats(); 989 stats.AddStream(stream_); 990 991 // Constructs an ssrc stats update. 992 cricket::VideoSenderInfo video_sender_info; 993 cricket::VideoMediaInfo stats_read; 994 const int64_t kBytesSent = 12345678901234LL; 995 996 // Construct a stats value to read. 997 video_sender_info.add_ssrc(1234); 998 video_sender_info.bytes_sent = kBytesSent; 999 stats_read.senders.push_back(video_sender_info); 1000 1001 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 1002 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 1003 EXPECT_CALL(*media_channel, GetStats(_)) 1004 .WillOnce(DoAll(SetArgPointee<0>(stats_read), 1005 Return(true))); 1006 1007 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1008 StatsReports reports; 1009 stats.GetStats(NULL, &reports); 1010 // |reports| should contain at least one session report, one track report, 1011 // and one ssrc report. 1012 EXPECT_LE((size_t)3, reports.size()); 1013 const StatsReport* track_report = FindNthReportByType( 1014 reports, StatsReport::kStatsReportTypeTrack, 1); 1015 EXPECT_TRUE(track_report); 1016 1017 // Get report for the specific |track|. 1018 reports.clear(); 1019 stats.GetStats(track_, &reports); 1020 // |reports| should contain at least one session report, one track report, 1021 // and one ssrc report. 1022 EXPECT_LE((size_t)3, reports.size()); 1023 track_report = FindNthReportByType( 1024 reports, StatsReport::kStatsReportTypeTrack, 1); 1025 EXPECT_TRUE(track_report); 1026 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); 1027 1028 std::string ssrc_id = ExtractSsrcStatsValue( 1029 reports, StatsReport::kStatsValueNameSsrc); 1030 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); 1031 1032 std::string track_id = ExtractSsrcStatsValue( 1033 reports, StatsReport::kStatsValueNameTrackId); 1034 EXPECT_EQ(kLocalTrackId, track_id); 1035} 1036 1037// This test verifies that an SSRC object has the identifier of a Transport 1038// stats object, and that this transport stats object exists in stats. 1039TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { 1040 StatsCollectorForTest stats(&pc_); 1041 1042 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1043 .WillRepeatedly(Return(false)); 1044 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1045 .WillRepeatedly(Return(false)); 1046 1047 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 1048 // The transport_name known by the video channel. 1049 const std::string kVcName("vcname"); 1050 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 1051 nullptr, kVcName, false); 1052 AddOutgoingVideoTrackStats(); 1053 stats.AddStream(stream_); 1054 1055 // Constructs an ssrc stats update. 1056 cricket::VideoSenderInfo video_sender_info; 1057 cricket::VideoMediaInfo stats_read; 1058 const int64_t kBytesSent = 12345678901234LL; 1059 1060 // Construct a stats value to read. 1061 video_sender_info.add_ssrc(1234); 1062 video_sender_info.bytes_sent = kBytesSent; 1063 stats_read.senders.push_back(video_sender_info); 1064 1065 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 1066 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 1067 EXPECT_CALL(*media_channel, GetStats(_)) 1068 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), 1069 Return(true))); 1070 1071 InitSessionStats(kVcName); 1072 EXPECT_CALL(session_, GetTransportStats(_)) 1073 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 1074 Return(true))); 1075 1076 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1077 StatsReports reports; 1078 stats.GetStats(NULL, &reports); 1079 std::string transport_id = ExtractStatsValue( 1080 StatsReport::kStatsReportTypeSsrc, 1081 reports, 1082 StatsReport::kStatsValueNameTransportId); 1083 ASSERT_NE(kNotFound, transport_id); 1084 // Transport id component ID will always be 1. 1085 // This has assumptions about how the ID is constructed. As is, this is 1086 // OK since this is for testing purposes only, but if we ever need this 1087 // in production, we should add a generic method that does this. 1088 size_t index = transport_id.find('-'); 1089 ASSERT_NE(std::string::npos, index); 1090 std::string content = transport_id.substr(index + 1); 1091 index = content.rfind('-'); 1092 ASSERT_NE(std::string::npos, index); 1093 content = content.substr(0, index); 1094 StatsReport::Id id(StatsReport::NewComponentId(content, 1)); 1095 ASSERT_EQ(transport_id, id->ToString()); 1096 const StatsReport* transport_report = FindReportById(reports, id); 1097 ASSERT_FALSE(transport_report == NULL); 1098} 1099 1100// This test verifies that a remote stats object will not be created for 1101// an outgoing SSRC where remote stats are not returned. 1102TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { 1103 StatsCollectorForTest stats(&pc_); 1104 1105 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 1106 // The transport_name known by the video channel. 1107 const std::string kVcName("vcname"); 1108 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 1109 nullptr, kVcName, false); 1110 AddOutgoingVideoTrackStats(); 1111 stats.AddStream(stream_); 1112 1113 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1114 StatsReports reports; 1115 stats.GetStats(NULL, &reports); 1116 const StatsReport* remote_report = FindNthReportByType(reports, 1117 StatsReport::kStatsReportTypeRemoteSsrc, 1); 1118 EXPECT_TRUE(remote_report == NULL); 1119} 1120 1121// This test verifies that a remote stats object will be created for 1122// an outgoing SSRC where stats are returned. 1123TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { 1124 StatsCollectorForTest stats(&pc_); 1125 1126 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1127 .WillRepeatedly(Return(false)); 1128 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1129 .WillRepeatedly(Return(false)); 1130 1131 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 1132 // The transport_name known by the video channel. 1133 const std::string kVcName("vcname"); 1134 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 1135 nullptr, kVcName, false); 1136 AddOutgoingVideoTrackStats(); 1137 stats.AddStream(stream_); 1138 1139 // Instruct the session to return stats containing the transport channel. 1140 InitSessionStats(kVcName); 1141 EXPECT_CALL(session_, GetTransportStats(_)) 1142 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 1143 Return(true))); 1144 1145 // Constructs an ssrc stats update. 1146 cricket::VideoMediaInfo stats_read; 1147 1148 cricket::SsrcReceiverInfo remote_ssrc_stats; 1149 remote_ssrc_stats.timestamp = 12345.678; 1150 remote_ssrc_stats.ssrc = kSsrcOfTrack; 1151 cricket::VideoSenderInfo video_sender_info; 1152 video_sender_info.add_ssrc(kSsrcOfTrack); 1153 video_sender_info.remote_stats.push_back(remote_ssrc_stats); 1154 stats_read.senders.push_back(video_sender_info); 1155 1156 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 1157 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 1158 EXPECT_CALL(*media_channel, GetStats(_)) 1159 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), 1160 Return(true))); 1161 1162 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1163 StatsReports reports; 1164 stats.GetStats(NULL, &reports); 1165 1166 const StatsReport* remote_report = FindNthReportByType(reports, 1167 StatsReport::kStatsReportTypeRemoteSsrc, 1); 1168 EXPECT_FALSE(remote_report == NULL); 1169 EXPECT_EQ(12345.678, remote_report->timestamp()); 1170} 1171 1172// This test verifies that the empty track report exists in the returned stats 1173// when StatsCollector::UpdateStats is called with ssrc stats. 1174TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) { 1175 StatsCollectorForTest stats(&pc_); 1176 1177 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1178 .WillRepeatedly(Return(false)); 1179 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1180 .WillRepeatedly(Return(false)); 1181 1182 const char kVideoChannelName[] = "video"; 1183 InitSessionStats(kVideoChannelName); 1184 EXPECT_CALL(session_, GetTransportStats(_)) 1185 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 1186 Return(true))); 1187 1188 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); 1189 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, 1190 nullptr, kVideoChannelName, false); 1191 AddIncomingVideoTrackStats(); 1192 stats.AddStream(stream_); 1193 1194 // Constructs an ssrc stats update. 1195 cricket::VideoReceiverInfo video_receiver_info; 1196 cricket::VideoMediaInfo stats_read; 1197 const int64_t kNumOfPacketsConcealed = 54321; 1198 1199 // Construct a stats value to read. 1200 video_receiver_info.add_ssrc(1234); 1201 video_receiver_info.packets_concealed = kNumOfPacketsConcealed; 1202 stats_read.receivers.push_back(video_receiver_info); 1203 1204 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); 1205 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); 1206 EXPECT_CALL(*media_channel, GetStats(_)) 1207 .WillOnce(DoAll(SetArgPointee<0>(stats_read), 1208 Return(true))); 1209 1210 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1211 StatsReports reports; 1212 stats.GetStats(NULL, &reports); 1213 // |reports| should contain at least one session report, one track report, 1214 // and one ssrc report. 1215 EXPECT_LE(static_cast<size_t>(3), reports.size()); 1216 const StatsReport* track_report = FindNthReportByType( 1217 reports, StatsReport::kStatsReportTypeTrack, 1); 1218 EXPECT_TRUE(track_report); 1219 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); 1220 1221 std::string ssrc_id = ExtractSsrcStatsValue( 1222 reports, StatsReport::kStatsValueNameSsrc); 1223 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); 1224 1225 std::string track_id = ExtractSsrcStatsValue( 1226 reports, StatsReport::kStatsValueNameTrackId); 1227 EXPECT_EQ(kRemoteTrackId, track_id); 1228} 1229 1230// This test verifies the Ice Candidate report should contain the correct 1231// information from local/remote candidates. 1232TEST_F(StatsCollectorTest, IceCandidateReport) { 1233 StatsCollectorForTest stats(&pc_); 1234 1235 StatsReports reports; // returned values. 1236 1237 const int local_port = 2000; 1238 const char local_ip[] = "192.168.0.1"; 1239 const int remote_port = 2001; 1240 const char remote_ip[] = "192.168.0.2"; 1241 1242 rtc::SocketAddress local_address(local_ip, local_port); 1243 rtc::SocketAddress remote_address(remote_ip, remote_port); 1244 rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; 1245 uint32_t priority = 1000; 1246 1247 cricket::Candidate c; 1248 ASSERT(c.id().length() > 0); 1249 c.set_type(cricket::LOCAL_PORT_TYPE); 1250 c.set_protocol(cricket::UDP_PROTOCOL_NAME); 1251 c.set_address(local_address); 1252 c.set_priority(priority); 1253 c.set_network_type(network_type); 1254 std::string report_id = AddCandidateReport(&stats, c, true)->id()->ToString(); 1255 EXPECT_EQ("Cand-" + c.id(), report_id); 1256 1257 c = cricket::Candidate(); 1258 ASSERT(c.id().length() > 0); 1259 c.set_type(cricket::PRFLX_PORT_TYPE); 1260 c.set_protocol(cricket::UDP_PROTOCOL_NAME); 1261 c.set_address(remote_address); 1262 c.set_priority(priority); 1263 c.set_network_type(network_type); 1264 report_id = AddCandidateReport(&stats, c, false)->id()->ToString(); 1265 EXPECT_EQ("Cand-" + c.id(), report_id); 1266 1267 stats.GetStats(NULL, &reports); 1268 1269 // Verify the local candidate report is populated correctly. 1270 EXPECT_EQ( 1271 local_ip, 1272 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1273 StatsReport::kStatsValueNameCandidateIPAddress)); 1274 EXPECT_EQ( 1275 rtc::ToString<int>(local_port), 1276 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1277 StatsReport::kStatsValueNameCandidatePortNumber)); 1278 EXPECT_EQ( 1279 cricket::UDP_PROTOCOL_NAME, 1280 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1281 StatsReport::kStatsValueNameCandidateTransportType)); 1282 EXPECT_EQ( 1283 rtc::ToString<int>(priority), 1284 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1285 StatsReport::kStatsValueNameCandidatePriority)); 1286 EXPECT_EQ( 1287 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), 1288 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1289 StatsReport::kStatsValueNameCandidateType)); 1290 EXPECT_EQ( 1291 AdapterTypeToStatsType(network_type), 1292 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, 1293 StatsReport::kStatsValueNameCandidateNetworkType)); 1294 1295 // Verify the remote candidate report is populated correctly. 1296 EXPECT_EQ(remote_ip, 1297 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, 1298 reports, 1299 StatsReport::kStatsValueNameCandidateIPAddress)); 1300 EXPECT_EQ(rtc::ToString<int>(remote_port), 1301 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, 1302 reports, 1303 StatsReport::kStatsValueNameCandidatePortNumber)); 1304 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, 1305 ExtractStatsValue( 1306 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, 1307 StatsReport::kStatsValueNameCandidateTransportType)); 1308 EXPECT_EQ(rtc::ToString<int>(priority), 1309 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, 1310 reports, 1311 StatsReport::kStatsValueNameCandidatePriority)); 1312 EXPECT_EQ( 1313 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), 1314 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, 1315 reports, StatsReport::kStatsValueNameCandidateType)); 1316 EXPECT_EQ(kNotFound, 1317 ExtractStatsValue( 1318 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, 1319 StatsReport::kStatsValueNameCandidateNetworkType)); 1320} 1321 1322// This test verifies that all chained certificates are correctly 1323// reported 1324TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { 1325 // Build local certificate chain. 1326 std::vector<std::string> local_ders(5); 1327 local_ders[0] = "These"; 1328 local_ders[1] = "are"; 1329 local_ders[2] = "some"; 1330 local_ders[3] = "der"; 1331 local_ders[4] = "values"; 1332 rtc::FakeSSLCertificate local_cert(DersToPems(local_ders)); 1333 1334 // Build remote certificate chain 1335 std::vector<std::string> remote_ders(4); 1336 remote_ders[0] = "A"; 1337 remote_ders[1] = "non-"; 1338 remote_ders[2] = "intersecting"; 1339 remote_ders[3] = "set"; 1340 rtc::FakeSSLCertificate remote_cert(DersToPems(remote_ders)); 1341 1342 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders); 1343} 1344 1345// This test verifies that all certificates without chains are correctly 1346// reported. 1347TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { 1348 // Build local certificate. 1349 std::string local_der = "This is the local der."; 1350 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); 1351 1352 // Build remote certificate. 1353 std::string remote_der = "This is somebody else's der."; 1354 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); 1355 1356 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), 1357 remote_cert, std::vector<std::string>(1, remote_der)); 1358} 1359 1360// This test verifies that the stats are generated correctly when no 1361// transport is present. 1362TEST_F(StatsCollectorTest, NoTransport) { 1363 StatsCollectorForTest stats(&pc_); 1364 1365 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1366 .WillRepeatedly(Return(false)); 1367 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1368 .WillRepeatedly(Return(false)); 1369 1370 StatsReports reports; // returned values. 1371 1372 // Fake stats to process. 1373 cricket::TransportChannelStats channel_stats; 1374 channel_stats.component = 1; 1375 1376 cricket::TransportStats transport_stats; 1377 transport_stats.transport_name = "audio"; 1378 transport_stats.channel_stats.push_back(channel_stats); 1379 1380 SessionStats session_stats; 1381 session_stats.transport_stats[transport_stats.transport_name] = 1382 transport_stats; 1383 1384 // Configure MockWebRtcSession 1385 EXPECT_CALL(session_, GetTransportStats(_)) 1386 .WillOnce(DoAll(SetArgPointee<0>(session_stats), 1387 Return(true))); 1388 1389 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1390 stats.GetStats(NULL, &reports); 1391 1392 // Check that the local certificate is absent. 1393 std::string local_certificate_id = ExtractStatsValue( 1394 StatsReport::kStatsReportTypeComponent, 1395 reports, 1396 StatsReport::kStatsValueNameLocalCertificateId); 1397 ASSERT_EQ(kNotFound, local_certificate_id); 1398 1399 // Check that the remote certificate is absent. 1400 std::string remote_certificate_id = ExtractStatsValue( 1401 StatsReport::kStatsReportTypeComponent, 1402 reports, 1403 StatsReport::kStatsValueNameRemoteCertificateId); 1404 ASSERT_EQ(kNotFound, remote_certificate_id); 1405 1406 // Check that the negotiated ciphers are absent. 1407 std::string dtls_cipher_suite = 1408 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, 1409 StatsReport::kStatsValueNameDtlsCipher); 1410 ASSERT_EQ(kNotFound, dtls_cipher_suite); 1411 std::string srtp_crypto_suite = 1412 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, 1413 StatsReport::kStatsValueNameSrtpCipher); 1414 ASSERT_EQ(kNotFound, srtp_crypto_suite); 1415} 1416 1417// This test verifies that the stats are generated correctly when the transport 1418// does not have any certificates. 1419TEST_F(StatsCollectorTest, NoCertificates) { 1420 StatsCollectorForTest stats(&pc_); 1421 1422 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1423 .WillRepeatedly(Return(false)); 1424 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1425 .WillRepeatedly(Return(false)); 1426 1427 StatsReports reports; // returned values. 1428 1429 // Fake stats to process. 1430 cricket::TransportChannelStats channel_stats; 1431 channel_stats.component = 1; 1432 1433 cricket::TransportStats transport_stats; 1434 transport_stats.transport_name = "audio"; 1435 transport_stats.channel_stats.push_back(channel_stats); 1436 1437 SessionStats session_stats; 1438 session_stats.transport_stats[transport_stats.transport_name] = 1439 transport_stats; 1440 1441 // Fake transport object. 1442 rtc::scoped_ptr<cricket::FakeTransport> transport( 1443 new cricket::FakeTransport(transport_stats.transport_name)); 1444 1445 // Configure MockWebRtcSession 1446 EXPECT_CALL(session_, GetTransportStats(_)) 1447 .WillOnce(DoAll(SetArgPointee<0>(session_stats), 1448 Return(true))); 1449 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1450 stats.GetStats(NULL, &reports); 1451 1452 // Check that the local certificate is absent. 1453 std::string local_certificate_id = ExtractStatsValue( 1454 StatsReport::kStatsReportTypeComponent, 1455 reports, 1456 StatsReport::kStatsValueNameLocalCertificateId); 1457 ASSERT_EQ(kNotFound, local_certificate_id); 1458 1459 // Check that the remote certificate is absent. 1460 std::string remote_certificate_id = ExtractStatsValue( 1461 StatsReport::kStatsReportTypeComponent, 1462 reports, 1463 StatsReport::kStatsValueNameRemoteCertificateId); 1464 ASSERT_EQ(kNotFound, remote_certificate_id); 1465} 1466 1467// This test verifies that a remote certificate with an unsupported digest 1468// algorithm is correctly ignored. 1469TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { 1470 // Build a local certificate. 1471 std::string local_der = "This is the local der."; 1472 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); 1473 1474 // Build a remote certificate with an unsupported digest algorithm. 1475 std::string remote_der = "This is somebody else's der."; 1476 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); 1477 remote_cert.set_digest_algorithm("foobar"); 1478 1479 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), 1480 remote_cert, std::vector<std::string>()); 1481} 1482 1483// This test verifies that a local stats object can get statistics via 1484// AudioTrackInterface::GetStats() method. 1485TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) { 1486 StatsCollectorForTest stats(&pc_); 1487 1488 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1489 .WillRepeatedly(Return(false)); 1490 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1491 .WillRepeatedly(Return(false)); 1492 1493 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); 1494 // The transport_name known by the voice channel. 1495 const std::string kVcName("vcname"); 1496 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, 1497 media_channel, nullptr, kVcName, false); 1498 AddOutgoingAudioTrackStats(); 1499 stats.AddStream(stream_); 1500 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); 1501 1502 cricket::VoiceSenderInfo voice_sender_info; 1503 InitVoiceSenderInfo(&voice_sender_info); 1504 1505 cricket::VoiceMediaInfo stats_read; 1506 StatsReports reports; // returned values. 1507 SetupAndVerifyAudioTrackStats( 1508 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, 1509 media_channel, &voice_sender_info, NULL, &stats_read, &reports); 1510 1511 // Verify that there is no remote report for the local audio track because 1512 // we did not set it up. 1513 const StatsReport* remote_report = FindNthReportByType(reports, 1514 StatsReport::kStatsReportTypeRemoteSsrc, 1); 1515 EXPECT_TRUE(remote_report == NULL); 1516} 1517 1518// This test verifies that audio receive streams populate stats reports 1519// correctly. 1520TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { 1521 StatsCollectorForTest stats(&pc_); 1522 1523 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1524 .WillRepeatedly(Return(false)); 1525 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1526 .WillRepeatedly(Return(false)); 1527 1528 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); 1529 // The transport_name known by the voice channel. 1530 const std::string kVcName("vcname"); 1531 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, 1532 media_channel, nullptr, kVcName, false); 1533 AddIncomingAudioTrackStats(); 1534 stats.AddStream(stream_); 1535 1536 cricket::VoiceReceiverInfo voice_receiver_info; 1537 InitVoiceReceiverInfo(&voice_receiver_info); 1538 voice_receiver_info.codec_name = "fake_codec"; 1539 1540 cricket::VoiceMediaInfo stats_read; 1541 StatsReports reports; // returned values. 1542 SetupAndVerifyAudioTrackStats( 1543 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, 1544 media_channel, NULL, &voice_receiver_info, &stats_read, &reports); 1545} 1546 1547// This test verifies that a local stats object won't update its statistics 1548// after a RemoveLocalAudioTrack() call. 1549TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) { 1550 StatsCollectorForTest stats(&pc_); 1551 1552 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1553 .WillRepeatedly(Return(false)); 1554 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1555 .WillRepeatedly(Return(false)); 1556 1557 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); 1558 // The transport_name known by the voice channel. 1559 const std::string kVcName("vcname"); 1560 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, 1561 media_channel, nullptr, kVcName, false); 1562 AddOutgoingAudioTrackStats(); 1563 stats.AddStream(stream_); 1564 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); 1565 1566 // Instruct the session to return stats containing the transport channel. 1567 InitSessionStats(kVcName); 1568 EXPECT_CALL(session_, GetTransportStats(_)) 1569 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 1570 Return(true))); 1571 1572 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); 1573 cricket::VoiceSenderInfo voice_sender_info; 1574 InitVoiceSenderInfo(&voice_sender_info); 1575 1576 // Constructs an ssrc stats update. 1577 cricket::VoiceMediaInfo stats_read; 1578 stats_read.senders.push_back(voice_sender_info); 1579 1580 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); 1581 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); 1582 EXPECT_CALL(*media_channel, GetStats(_)) 1583 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), 1584 Return(true))); 1585 1586 StatsReports reports; // returned values. 1587 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1588 stats.GetStats(NULL, &reports); 1589 1590 // The report will exist since we don't remove them in RemoveStream(). 1591 const StatsReport* report = FindNthReportByType( 1592 reports, StatsReport::kStatsReportTypeSsrc, 1); 1593 EXPECT_FALSE(report == NULL); 1594 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); 1595 std::string track_id = ExtractSsrcStatsValue( 1596 reports, StatsReport::kStatsValueNameTrackId); 1597 EXPECT_EQ(kLocalTrackId, track_id); 1598 std::string ssrc_id = ExtractSsrcStatsValue( 1599 reports, StatsReport::kStatsValueNameSsrc); 1600 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); 1601 1602 // Verifies the values in the track report, no value will be changed by the 1603 // AudioTrackInterface::GetSignalValue() and 1604 // AudioProcessorInterface::AudioProcessorStats::GetStats(); 1605 VerifyVoiceSenderInfoReport(report, voice_sender_info); 1606} 1607 1608// This test verifies that when ongoing and incoming audio tracks are using 1609// the same ssrc, they populate stats reports correctly. 1610TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { 1611 StatsCollectorForTest stats(&pc_); 1612 1613 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1614 .WillRepeatedly(Return(false)); 1615 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1616 .WillRepeatedly(Return(false)); 1617 1618 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); 1619 // The transport_name known by the voice channel. 1620 const std::string kVcName("vcname"); 1621 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, 1622 media_channel, nullptr, kVcName, false); 1623 1624 // Create a local stream with a local audio track and adds it to the stats. 1625 AddOutgoingAudioTrackStats(); 1626 stats.AddStream(stream_); 1627 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); 1628 1629 // Create a remote stream with a remote audio track and adds it to the stats. 1630 rtc::scoped_refptr<webrtc::MediaStream> remote_stream( 1631 webrtc::MediaStream::Create("remotestreamlabel")); 1632 rtc::scoped_refptr<FakeAudioTrack> remote_track( 1633 new rtc::RefCountedObject<FakeAudioTrack>(kRemoteTrackId)); 1634 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) 1635 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); 1636 remote_stream->AddTrack(remote_track); 1637 stats.AddStream(remote_stream); 1638 1639 // Instruct the session to return stats containing the transport channel. 1640 InitSessionStats(kVcName); 1641 EXPECT_CALL(session_, GetTransportStats(_)) 1642 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), 1643 Return(true))); 1644 1645 cricket::VoiceSenderInfo voice_sender_info; 1646 InitVoiceSenderInfo(&voice_sender_info); 1647 1648 // Some of the contents in |voice_sender_info| needs to be updated from the 1649 // |audio_track_|. 1650 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info); 1651 1652 cricket::VoiceReceiverInfo voice_receiver_info; 1653 InitVoiceReceiverInfo(&voice_receiver_info); 1654 1655 // Constructs an ssrc stats update. 1656 cricket::VoiceMediaInfo stats_read; 1657 stats_read.senders.push_back(voice_sender_info); 1658 stats_read.receivers.push_back(voice_receiver_info); 1659 1660 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); 1661 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); 1662 EXPECT_CALL(*media_channel, GetStats(_)) 1663 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), 1664 Return(true))); 1665 1666 StatsReports reports; // returned values. 1667 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); 1668 1669 // Get stats for the local track. 1670 stats.GetStats(audio_track_.get(), &reports); 1671 const StatsReport* track_report = FindNthReportByType( 1672 reports, StatsReport::kStatsReportTypeSsrc, 1); 1673 EXPECT_TRUE(track_report); 1674 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); 1675 std::string track_id = ExtractSsrcStatsValue( 1676 reports, StatsReport::kStatsValueNameTrackId); 1677 EXPECT_EQ(kLocalTrackId, track_id); 1678 VerifyVoiceSenderInfoReport(track_report, voice_sender_info); 1679 1680 // Get stats for the remote track. 1681 reports.clear(); 1682 stats.GetStats(remote_track.get(), &reports); 1683 track_report = FindNthReportByType(reports, 1684 StatsReport::kStatsReportTypeSsrc, 1); 1685 EXPECT_TRUE(track_report); 1686 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); 1687 track_id = ExtractSsrcStatsValue(reports, 1688 StatsReport::kStatsValueNameTrackId); 1689 EXPECT_EQ(kRemoteTrackId, track_id); 1690 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info); 1691} 1692 1693// This test verifies that when two outgoing audio tracks are using the same 1694// ssrc at different times, they populate stats reports correctly. 1695// TODO(xians): Figure out if it is possible to encapsulate the setup and 1696// avoid duplication of code in test cases. 1697TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { 1698 StatsCollectorForTest stats(&pc_); 1699 1700 EXPECT_CALL(session_, GetLocalCertificate(_, _)) 1701 .WillRepeatedly(Return(false)); 1702 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) 1703 .WillRepeatedly(Return(false)); 1704 1705 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); 1706 // The transport_name known by the voice channel. 1707 const std::string kVcName("vcname"); 1708 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, 1709 media_channel, nullptr, kVcName, false); 1710 1711 // Create a local stream with a local audio track and adds it to the stats. 1712 AddOutgoingAudioTrackStats(); 1713 stats.AddStream(stream_); 1714 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); 1715 1716 cricket::VoiceSenderInfo voice_sender_info; 1717 voice_sender_info.add_ssrc(kSsrcOfTrack); 1718 1719 cricket::VoiceMediaInfo stats_read; 1720 StatsReports reports; // returned values. 1721 SetupAndVerifyAudioTrackStats( 1722 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, 1723 media_channel, &voice_sender_info, NULL, &stats_read, &reports); 1724 1725 // Remove the previous audio track from the stream. 1726 stream_->RemoveTrack(audio_track_.get()); 1727 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); 1728 1729 // Create a new audio track and adds it to the stream and stats. 1730 static const std::string kNewTrackId = "new_track_id"; 1731 rtc::scoped_refptr<FakeAudioTrack> new_audio_track( 1732 new rtc::RefCountedObject<FakeAudioTrack>(kNewTrackId)); 1733 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) 1734 .WillOnce(DoAll(SetArgPointee<1>(kNewTrackId), Return(true))); 1735 stream_->AddTrack(new_audio_track); 1736 1737 stats.AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); 1738 stats.ClearUpdateStatsCacheForTest(); 1739 cricket::VoiceSenderInfo new_voice_sender_info; 1740 InitVoiceSenderInfo(&new_voice_sender_info); 1741 cricket::VoiceMediaInfo new_stats_read; 1742 reports.clear(); 1743 SetupAndVerifyAudioTrackStats( 1744 new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, 1745 media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); 1746} 1747 1748} // namespace webrtc 1749