| OLD | NEW |
| (Empty) |
| 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/mediastream.h" | |
| 35 #include "talk/app/webrtc/mediastreaminterface.h" | |
| 36 #include "talk/app/webrtc/mediastreamtrack.h" | |
| 37 #include "talk/app/webrtc/peerconnection.h" | |
| 38 #include "talk/app/webrtc/peerconnectionfactory.h" | |
| 39 #include "talk/app/webrtc/test/fakedatachannelprovider.h" | |
| 40 #include "talk/app/webrtc/videotrack.h" | |
| 41 #include "talk/session/media/channelmanager.h" | |
| 42 #include "testing/gmock/include/gmock/gmock.h" | |
| 43 #include "testing/gtest/include/gtest/gtest.h" | |
| 44 #include "webrtc/base/base64.h" | |
| 45 #include "webrtc/base/fakesslidentity.h" | |
| 46 #include "webrtc/base/gunit.h" | |
| 47 #include "webrtc/base/network.h" | |
| 48 #include "webrtc/media/base/fakemediaengine.h" | |
| 49 #include "webrtc/p2p/base/faketransportcontroller.h" | |
| 50 | |
| 51 using rtc::scoped_ptr; | |
| 52 using testing::_; | |
| 53 using testing::DoAll; | |
| 54 using testing::Field; | |
| 55 using testing::Return; | |
| 56 using testing::ReturnNull; | |
| 57 using testing::ReturnRef; | |
| 58 using testing::SetArgPointee; | |
| 59 using webrtc::PeerConnectionInterface; | |
| 60 using webrtc::StatsReport; | |
| 61 using webrtc::StatsReports; | |
| 62 | |
| 63 namespace { | |
| 64 // This value comes from openssl/tls1.h | |
| 65 const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014; | |
| 66 } // namespace | |
| 67 | |
| 68 namespace cricket { | |
| 69 | |
| 70 class ChannelManager; | |
| 71 | |
| 72 } // namespace cricket | |
| 73 | |
| 74 namespace webrtc { | |
| 75 | |
| 76 // Error return values | |
| 77 const char kNotFound[] = "NOT FOUND"; | |
| 78 | |
| 79 // Constant names for track identification. | |
| 80 const char kLocalTrackId[] = "local_track_id"; | |
| 81 const char kRemoteTrackId[] = "remote_track_id"; | |
| 82 const uint32_t kSsrcOfTrack = 1234; | |
| 83 | |
| 84 class 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. | |
| 107 class FakePeerConnectionFactory | |
| 108 : public rtc::RefCountedObject<PeerConnectionFactory> {}; | |
| 109 | |
| 110 class 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 | |
| 121 class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel { | |
| 122 public: | |
| 123 MockVideoMediaChannel() : | |
| 124 cricket::FakeVideoMediaChannel(NULL, cricket::VideoOptions()) {} | |
| 125 MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*)); | |
| 126 }; | |
| 127 | |
| 128 class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel { | |
| 129 public: | |
| 130 MockVoiceMediaChannel() : | |
| 131 cricket::FakeVoiceMediaChannel(NULL, cricket::AudioOptions()) {} | |
| 132 MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*)); | |
| 133 }; | |
| 134 | |
| 135 class 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 | |
| 151 class 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 | |
| 174 bool 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 | |
| 184 std::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 | |
| 196 StatsReport::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 | |
| 216 StatsReport::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. | |
| 222 const 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 | |
| 234 const 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 | |
| 243 std::string ExtractSsrcStatsValue(StatsReports reports, | |
| 244 StatsReport::StatsValueName name) { | |
| 245 return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name); | |
| 246 } | |
| 247 | |
| 248 std::string ExtractBweStatsValue(StatsReports reports, | |
| 249 StatsReport::StatsValueName name) { | |
| 250 return ExtractStatsValue( | |
| 251 StatsReport::kStatsReportTypeBwe, reports, name); | |
| 252 } | |
| 253 | |
| 254 std::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 | |
| 261 std::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 | |
| 268 void 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 | |
| 311 void 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 | |
| 378 void 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. | |
| 433 void 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 | |
| 452 void 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 | |
| 469 void 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 | |
| 489 class 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 | |
| 502 class 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 std::string media_type = ExtractSsrcStatsValue(*reports, | |
| 647 StatsReport::kStatsValueNameMediaType); | |
| 648 EXPECT_EQ("audio", media_type); | |
| 649 | |
| 650 // Verifies the values in the track report. | |
| 651 if (voice_sender_info) { | |
| 652 UpdateVoiceSenderInfoFromAudioTrack(audio_track, voice_sender_info); | |
| 653 VerifyVoiceSenderInfoReport(report, *voice_sender_info); | |
| 654 } | |
| 655 if (voice_receiver_info) { | |
| 656 VerifyVoiceReceiverInfoReport(report, *voice_receiver_info); | |
| 657 } | |
| 658 | |
| 659 // Verify we get the same result by passing a track to GetStats(). | |
| 660 StatsReports track_reports; // returned values. | |
| 661 stats->GetStats(audio_track, &track_reports); | |
| 662 const StatsReport* track_report = FindNthReportByType( | |
| 663 track_reports, StatsReport::kStatsReportTypeSsrc, 1); | |
| 664 EXPECT_TRUE(track_report); | |
| 665 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); | |
| 666 track_id = ExtractSsrcStatsValue(track_reports, | |
| 667 StatsReport::kStatsValueNameTrackId); | |
| 668 EXPECT_EQ(audio_track->id(), track_id); | |
| 669 ssrc_id = ExtractSsrcStatsValue(track_reports, | |
| 670 StatsReport::kStatsValueNameSsrc); | |
| 671 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
| 672 if (voice_sender_info) | |
| 673 VerifyVoiceSenderInfoReport(track_report, *voice_sender_info); | |
| 674 if (voice_receiver_info) | |
| 675 VerifyVoiceReceiverInfoReport(track_report, *voice_receiver_info); | |
| 676 } | |
| 677 | |
| 678 void TestCertificateReports(const rtc::FakeSSLCertificate& local_cert, | |
| 679 const std::vector<std::string>& local_ders, | |
| 680 const rtc::FakeSSLCertificate& remote_cert, | |
| 681 const std::vector<std::string>& remote_ders) { | |
| 682 StatsCollectorForTest stats(&pc_); | |
| 683 | |
| 684 StatsReports reports; // returned values. | |
| 685 | |
| 686 // Fake stats to process. | |
| 687 cricket::TransportChannelStats channel_stats; | |
| 688 channel_stats.component = 1; | |
| 689 channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; | |
| 690 channel_stats.ssl_cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; | |
| 691 | |
| 692 cricket::TransportStats transport_stats; | |
| 693 transport_stats.transport_name = "audio"; | |
| 694 transport_stats.channel_stats.push_back(channel_stats); | |
| 695 | |
| 696 SessionStats session_stats; | |
| 697 session_stats.transport_stats[transport_stats.transport_name] = | |
| 698 transport_stats; | |
| 699 | |
| 700 // Fake certificate to report | |
| 701 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate( | |
| 702 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::FakeSSLIdentity>( | |
| 703 new rtc::FakeSSLIdentity(local_cert)))); | |
| 704 | |
| 705 // Configure MockWebRtcSession | |
| 706 EXPECT_CALL(session_, | |
| 707 GetLocalCertificate(transport_stats.transport_name, _)) | |
| 708 .WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true))); | |
| 709 EXPECT_CALL(session_, | |
| 710 GetRemoteSSLCertificate(transport_stats.transport_name, _)) | |
| 711 .WillOnce( | |
| 712 DoAll(SetArgPointee<1>(remote_cert.GetReference()), Return(true))); | |
| 713 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 714 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
| 715 Return(true))); | |
| 716 | |
| 717 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 718 | |
| 719 stats.GetStats(NULL, &reports); | |
| 720 | |
| 721 const StatsReport* channel_report = FindNthReportByType( | |
| 722 reports, StatsReport::kStatsReportTypeComponent, 1); | |
| 723 EXPECT_TRUE(channel_report != NULL); | |
| 724 | |
| 725 // Check local certificate chain. | |
| 726 std::string local_certificate_id = ExtractStatsValue( | |
| 727 StatsReport::kStatsReportTypeComponent, | |
| 728 reports, | |
| 729 StatsReport::kStatsValueNameLocalCertificateId); | |
| 730 if (local_ders.size() > 0) { | |
| 731 EXPECT_NE(kNotFound, local_certificate_id); | |
| 732 StatsReport::Id id(IdFromCertIdString(local_certificate_id)); | |
| 733 CheckCertChainReports(reports, local_ders, id); | |
| 734 } else { | |
| 735 EXPECT_EQ(kNotFound, local_certificate_id); | |
| 736 } | |
| 737 | |
| 738 // Check remote certificate chain. | |
| 739 std::string remote_certificate_id = ExtractStatsValue( | |
| 740 StatsReport::kStatsReportTypeComponent, | |
| 741 reports, | |
| 742 StatsReport::kStatsValueNameRemoteCertificateId); | |
| 743 if (remote_ders.size() > 0) { | |
| 744 EXPECT_NE(kNotFound, remote_certificate_id); | |
| 745 StatsReport::Id id(IdFromCertIdString(remote_certificate_id)); | |
| 746 CheckCertChainReports(reports, remote_ders, id); | |
| 747 } else { | |
| 748 EXPECT_EQ(kNotFound, remote_certificate_id); | |
| 749 } | |
| 750 | |
| 751 // Check negotiated ciphers. | |
| 752 std::string dtls_cipher_suite = | |
| 753 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
| 754 StatsReport::kStatsValueNameDtlsCipher); | |
| 755 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName( | |
| 756 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), | |
| 757 dtls_cipher_suite); | |
| 758 std::string srtp_crypto_suite = | |
| 759 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
| 760 StatsReport::kStatsValueNameSrtpCipher); | |
| 761 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::SRTP_AES128_CM_SHA1_80), | |
| 762 srtp_crypto_suite); | |
| 763 } | |
| 764 | |
| 765 cricket::FakeMediaEngine* media_engine_; | |
| 766 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; | |
| 767 rtc::scoped_ptr<webrtc::MediaControllerInterface> media_controller_; | |
| 768 MockWebRtcSession session_; | |
| 769 MockPeerConnection pc_; | |
| 770 FakeDataChannelProvider data_channel_provider_; | |
| 771 SessionStats session_stats_; | |
| 772 rtc::scoped_refptr<webrtc::MediaStream> stream_; | |
| 773 rtc::scoped_refptr<webrtc::VideoTrack> track_; | |
| 774 rtc::scoped_refptr<FakeAudioTrack> audio_track_; | |
| 775 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; | |
| 776 }; | |
| 777 | |
| 778 // Verify that ExtractDataInfo populates reports. | |
| 779 TEST_F(StatsCollectorTest, ExtractDataInfo) { | |
| 780 const std::string label = "hacks"; | |
| 781 const int id = 31337; | |
| 782 const std::string state = DataChannelInterface::DataStateString( | |
| 783 DataChannelInterface::DataState::kConnecting); | |
| 784 | |
| 785 AddDataChannel(cricket::DCT_SCTP, label, id); | |
| 786 StatsCollectorForTest stats(&pc_); | |
| 787 | |
| 788 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 789 | |
| 790 StatsReports reports; | |
| 791 stats.GetStats(NULL, &reports); | |
| 792 | |
| 793 const StatsReport* report = | |
| 794 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); | |
| 795 | |
| 796 StatsReport::Id reportId = StatsReport::NewTypedIntId( | |
| 797 StatsReport::kStatsReportTypeDataChannel, id); | |
| 798 | |
| 799 EXPECT_TRUE(reportId->Equals(report->id())); | |
| 800 | |
| 801 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
| 802 EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
| 803 reports, | |
| 804 StatsReport::kStatsValueNameLabel)); | |
| 805 EXPECT_EQ(rtc::ToString<int64_t>(id), | |
| 806 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, | |
| 807 StatsReport::kStatsValueNameDataChannelId)); | |
| 808 EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
| 809 reports, | |
| 810 StatsReport::kStatsValueNameState)); | |
| 811 EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
| 812 reports, | |
| 813 StatsReport::kStatsValueNameProtocol)); | |
| 814 } | |
| 815 | |
| 816 // This test verifies that 64-bit counters are passed successfully. | |
| 817 TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { | |
| 818 StatsCollectorForTest stats(&pc_); | |
| 819 | |
| 820 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 821 .WillRepeatedly(Return(false)); | |
| 822 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 823 .WillRepeatedly(Return(false)); | |
| 824 | |
| 825 const char kVideoChannelName[] = "video"; | |
| 826 | |
| 827 InitSessionStats(kVideoChannelName); | |
| 828 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 829 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 830 Return(true))); | |
| 831 | |
| 832 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 833 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 834 nullptr, kVideoChannelName, false); | |
| 835 StatsReports reports; // returned values. | |
| 836 cricket::VideoSenderInfo video_sender_info; | |
| 837 cricket::VideoMediaInfo stats_read; | |
| 838 // The number of bytes must be larger than 0xFFFFFFFF for this test. | |
| 839 const int64_t kBytesSent = 12345678901234LL; | |
| 840 const std::string kBytesSentString("12345678901234"); | |
| 841 | |
| 842 AddOutgoingVideoTrackStats(); | |
| 843 stats.AddStream(stream_); | |
| 844 | |
| 845 // Construct a stats value to read. | |
| 846 video_sender_info.add_ssrc(1234); | |
| 847 video_sender_info.bytes_sent = kBytesSent; | |
| 848 stats_read.senders.push_back(video_sender_info); | |
| 849 | |
| 850 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 851 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 852 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 853 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
| 854 Return(true))); | |
| 855 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 856 stats.GetStats(NULL, &reports); | |
| 857 std::string result = ExtractSsrcStatsValue(reports, | |
| 858 StatsReport::kStatsValueNameBytesSent); | |
| 859 EXPECT_EQ(kBytesSentString, result); | |
| 860 } | |
| 861 | |
| 862 // Test that BWE information is reported via stats. | |
| 863 TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { | |
| 864 StatsCollectorForTest stats(&pc_); | |
| 865 | |
| 866 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 867 .WillRepeatedly(Return(false)); | |
| 868 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 869 .WillRepeatedly(Return(false)); | |
| 870 | |
| 871 const char kVideoChannelName[] = "video"; | |
| 872 | |
| 873 InitSessionStats(kVideoChannelName); | |
| 874 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 875 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 876 Return(true))); | |
| 877 | |
| 878 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 879 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 880 nullptr, kVideoChannelName, false); | |
| 881 | |
| 882 StatsReports reports; // returned values. | |
| 883 cricket::VideoSenderInfo video_sender_info; | |
| 884 cricket::VideoMediaInfo stats_read; | |
| 885 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and | |
| 886 // BWE. | |
| 887 const int64_t kBytesSent = 12345678901234LL; | |
| 888 const std::string kBytesSentString("12345678901234"); | |
| 889 | |
| 890 AddOutgoingVideoTrackStats(); | |
| 891 stats.AddStream(stream_); | |
| 892 | |
| 893 // Construct a stats value to read. | |
| 894 video_sender_info.add_ssrc(1234); | |
| 895 video_sender_info.bytes_sent = kBytesSent; | |
| 896 stats_read.senders.push_back(video_sender_info); | |
| 897 cricket::BandwidthEstimationInfo bwe; | |
| 898 const int kTargetEncBitrate = 123456; | |
| 899 const std::string kTargetEncBitrateString("123456"); | |
| 900 bwe.target_enc_bitrate = kTargetEncBitrate; | |
| 901 stats_read.bw_estimations.push_back(bwe); | |
| 902 | |
| 903 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 904 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 905 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 906 .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); | |
| 907 | |
| 908 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 909 stats.GetStats(NULL, &reports); | |
| 910 std::string result = ExtractSsrcStatsValue(reports, | |
| 911 StatsReport::kStatsValueNameBytesSent); | |
| 912 EXPECT_EQ(kBytesSentString, result); | |
| 913 result = ExtractBweStatsValue(reports, | |
| 914 StatsReport::kStatsValueNameTargetEncBitrate); | |
| 915 EXPECT_EQ(kTargetEncBitrateString, result); | |
| 916 } | |
| 917 | |
| 918 // This test verifies that an object of type "googSession" always | |
| 919 // exists in the returned stats. | |
| 920 TEST_F(StatsCollectorTest, SessionObjectExists) { | |
| 921 StatsCollectorForTest stats(&pc_); | |
| 922 | |
| 923 StatsReports reports; // returned values. | |
| 924 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 925 stats.GetStats(NULL, &reports); | |
| 926 const StatsReport* session_report = FindNthReportByType( | |
| 927 reports, StatsReport::kStatsReportTypeSession, 1); | |
| 928 EXPECT_FALSE(session_report == NULL); | |
| 929 } | |
| 930 | |
| 931 // This test verifies that only one object of type "googSession" exists | |
| 932 // in the returned stats. | |
| 933 TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { | |
| 934 StatsCollectorForTest stats(&pc_); | |
| 935 | |
| 936 StatsReports reports; // returned values. | |
| 937 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 938 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 939 stats.GetStats(NULL, &reports); | |
| 940 const StatsReport* session_report = FindNthReportByType( | |
| 941 reports, StatsReport::kStatsReportTypeSession, 1); | |
| 942 EXPECT_FALSE(session_report == NULL); | |
| 943 session_report = FindNthReportByType( | |
| 944 reports, StatsReport::kStatsReportTypeSession, 2); | |
| 945 EXPECT_EQ(NULL, session_report); | |
| 946 } | |
| 947 | |
| 948 // This test verifies that the empty track report exists in the returned stats | |
| 949 // without calling StatsCollector::UpdateStats. | |
| 950 TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { | |
| 951 StatsCollectorForTest stats(&pc_); | |
| 952 | |
| 953 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 954 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 955 nullptr, "video", false); | |
| 956 AddOutgoingVideoTrackStats(); | |
| 957 stats.AddStream(stream_); | |
| 958 | |
| 959 // Verfies the existence of the track report. | |
| 960 StatsReports reports; | |
| 961 stats.GetStats(NULL, &reports); | |
| 962 EXPECT_EQ((size_t)1, reports.size()); | |
| 963 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type()); | |
| 964 EXPECT_EQ(0, reports[0]->timestamp()); | |
| 965 | |
| 966 std::string trackValue = | |
| 967 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, | |
| 968 reports, | |
| 969 StatsReport::kStatsValueNameTrackId); | |
| 970 EXPECT_EQ(kLocalTrackId, trackValue); | |
| 971 } | |
| 972 | |
| 973 // This test verifies that the empty track report exists in the returned stats | |
| 974 // when StatsCollector::UpdateStats is called with ssrc stats. | |
| 975 TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { | |
| 976 StatsCollectorForTest stats(&pc_); | |
| 977 | |
| 978 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 979 .WillRepeatedly(Return(false)); | |
| 980 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 981 .WillRepeatedly(Return(false)); | |
| 982 | |
| 983 const char kVideoChannelName[] = "video"; | |
| 984 InitSessionStats(kVideoChannelName); | |
| 985 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 986 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 987 Return(true))); | |
| 988 | |
| 989 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 990 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 991 nullptr, kVideoChannelName, false); | |
| 992 AddOutgoingVideoTrackStats(); | |
| 993 stats.AddStream(stream_); | |
| 994 | |
| 995 // Constructs an ssrc stats update. | |
| 996 cricket::VideoSenderInfo video_sender_info; | |
| 997 cricket::VideoMediaInfo stats_read; | |
| 998 const int64_t kBytesSent = 12345678901234LL; | |
| 999 | |
| 1000 // Construct a stats value to read. | |
| 1001 video_sender_info.add_ssrc(1234); | |
| 1002 video_sender_info.bytes_sent = kBytesSent; | |
| 1003 stats_read.senders.push_back(video_sender_info); | |
| 1004 | |
| 1005 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 1006 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 1007 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1008 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
| 1009 Return(true))); | |
| 1010 | |
| 1011 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1012 StatsReports reports; | |
| 1013 stats.GetStats(NULL, &reports); | |
| 1014 // |reports| should contain at least one session report, one track report, | |
| 1015 // and one ssrc report. | |
| 1016 EXPECT_LE((size_t)3, reports.size()); | |
| 1017 const StatsReport* track_report = FindNthReportByType( | |
| 1018 reports, StatsReport::kStatsReportTypeTrack, 1); | |
| 1019 EXPECT_TRUE(track_report); | |
| 1020 | |
| 1021 // Get report for the specific |track|. | |
| 1022 reports.clear(); | |
| 1023 stats.GetStats(track_, &reports); | |
| 1024 // |reports| should contain at least one session report, one track report, | |
| 1025 // and one ssrc report. | |
| 1026 EXPECT_LE((size_t)3, reports.size()); | |
| 1027 track_report = FindNthReportByType( | |
| 1028 reports, StatsReport::kStatsReportTypeTrack, 1); | |
| 1029 EXPECT_TRUE(track_report); | |
| 1030 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
| 1031 | |
| 1032 std::string ssrc_id = ExtractSsrcStatsValue( | |
| 1033 reports, StatsReport::kStatsValueNameSsrc); | |
| 1034 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
| 1035 | |
| 1036 std::string track_id = ExtractSsrcStatsValue( | |
| 1037 reports, StatsReport::kStatsValueNameTrackId); | |
| 1038 EXPECT_EQ(kLocalTrackId, track_id); | |
| 1039 | |
| 1040 std::string media_type = ExtractSsrcStatsValue(reports, | |
| 1041 StatsReport::kStatsValueNameMediaType); | |
| 1042 EXPECT_EQ("video", media_type); | |
| 1043 } | |
| 1044 | |
| 1045 // This test verifies that an SSRC object has the identifier of a Transport | |
| 1046 // stats object, and that this transport stats object exists in stats. | |
| 1047 TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { | |
| 1048 StatsCollectorForTest stats(&pc_); | |
| 1049 | |
| 1050 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1051 .WillRepeatedly(Return(false)); | |
| 1052 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1053 .WillRepeatedly(Return(false)); | |
| 1054 | |
| 1055 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 1056 // The transport_name known by the video channel. | |
| 1057 const std::string kVcName("vcname"); | |
| 1058 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 1059 nullptr, kVcName, false); | |
| 1060 AddOutgoingVideoTrackStats(); | |
| 1061 stats.AddStream(stream_); | |
| 1062 | |
| 1063 // Constructs an ssrc stats update. | |
| 1064 cricket::VideoSenderInfo video_sender_info; | |
| 1065 cricket::VideoMediaInfo stats_read; | |
| 1066 const int64_t kBytesSent = 12345678901234LL; | |
| 1067 | |
| 1068 // Construct a stats value to read. | |
| 1069 video_sender_info.add_ssrc(1234); | |
| 1070 video_sender_info.bytes_sent = kBytesSent; | |
| 1071 stats_read.senders.push_back(video_sender_info); | |
| 1072 | |
| 1073 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 1074 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 1075 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1076 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
| 1077 Return(true))); | |
| 1078 | |
| 1079 InitSessionStats(kVcName); | |
| 1080 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1081 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 1082 Return(true))); | |
| 1083 | |
| 1084 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1085 StatsReports reports; | |
| 1086 stats.GetStats(NULL, &reports); | |
| 1087 std::string transport_id = ExtractStatsValue( | |
| 1088 StatsReport::kStatsReportTypeSsrc, | |
| 1089 reports, | |
| 1090 StatsReport::kStatsValueNameTransportId); | |
| 1091 ASSERT_NE(kNotFound, transport_id); | |
| 1092 // Transport id component ID will always be 1. | |
| 1093 // This has assumptions about how the ID is constructed. As is, this is | |
| 1094 // OK since this is for testing purposes only, but if we ever need this | |
| 1095 // in production, we should add a generic method that does this. | |
| 1096 size_t index = transport_id.find('-'); | |
| 1097 ASSERT_NE(std::string::npos, index); | |
| 1098 std::string content = transport_id.substr(index + 1); | |
| 1099 index = content.rfind('-'); | |
| 1100 ASSERT_NE(std::string::npos, index); | |
| 1101 content = content.substr(0, index); | |
| 1102 StatsReport::Id id(StatsReport::NewComponentId(content, 1)); | |
| 1103 ASSERT_EQ(transport_id, id->ToString()); | |
| 1104 const StatsReport* transport_report = FindReportById(reports, id); | |
| 1105 ASSERT_FALSE(transport_report == NULL); | |
| 1106 } | |
| 1107 | |
| 1108 // This test verifies that a remote stats object will not be created for | |
| 1109 // an outgoing SSRC where remote stats are not returned. | |
| 1110 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { | |
| 1111 StatsCollectorForTest stats(&pc_); | |
| 1112 | |
| 1113 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 1114 // The transport_name known by the video channel. | |
| 1115 const std::string kVcName("vcname"); | |
| 1116 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 1117 nullptr, kVcName, false); | |
| 1118 AddOutgoingVideoTrackStats(); | |
| 1119 stats.AddStream(stream_); | |
| 1120 | |
| 1121 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1122 StatsReports reports; | |
| 1123 stats.GetStats(NULL, &reports); | |
| 1124 const StatsReport* remote_report = FindNthReportByType(reports, | |
| 1125 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
| 1126 EXPECT_TRUE(remote_report == NULL); | |
| 1127 } | |
| 1128 | |
| 1129 // This test verifies that a remote stats object will be created for | |
| 1130 // an outgoing SSRC where stats are returned. | |
| 1131 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { | |
| 1132 StatsCollectorForTest stats(&pc_); | |
| 1133 | |
| 1134 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1135 .WillRepeatedly(Return(false)); | |
| 1136 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1137 .WillRepeatedly(Return(false)); | |
| 1138 | |
| 1139 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 1140 // The transport_name known by the video channel. | |
| 1141 const std::string kVcName("vcname"); | |
| 1142 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 1143 nullptr, kVcName, false); | |
| 1144 AddOutgoingVideoTrackStats(); | |
| 1145 stats.AddStream(stream_); | |
| 1146 | |
| 1147 // Instruct the session to return stats containing the transport channel. | |
| 1148 InitSessionStats(kVcName); | |
| 1149 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1150 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 1151 Return(true))); | |
| 1152 | |
| 1153 // Constructs an ssrc stats update. | |
| 1154 cricket::VideoMediaInfo stats_read; | |
| 1155 | |
| 1156 cricket::SsrcReceiverInfo remote_ssrc_stats; | |
| 1157 remote_ssrc_stats.timestamp = 12345.678; | |
| 1158 remote_ssrc_stats.ssrc = kSsrcOfTrack; | |
| 1159 cricket::VideoSenderInfo video_sender_info; | |
| 1160 video_sender_info.add_ssrc(kSsrcOfTrack); | |
| 1161 video_sender_info.remote_stats.push_back(remote_ssrc_stats); | |
| 1162 stats_read.senders.push_back(video_sender_info); | |
| 1163 | |
| 1164 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 1165 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 1166 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1167 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
| 1168 Return(true))); | |
| 1169 | |
| 1170 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1171 StatsReports reports; | |
| 1172 stats.GetStats(NULL, &reports); | |
| 1173 | |
| 1174 const StatsReport* remote_report = FindNthReportByType(reports, | |
| 1175 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
| 1176 EXPECT_FALSE(remote_report == NULL); | |
| 1177 EXPECT_EQ(12345.678, remote_report->timestamp()); | |
| 1178 } | |
| 1179 | |
| 1180 // This test verifies that the empty track report exists in the returned stats | |
| 1181 // when StatsCollector::UpdateStats is called with ssrc stats. | |
| 1182 TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) { | |
| 1183 StatsCollectorForTest stats(&pc_); | |
| 1184 | |
| 1185 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1186 .WillRepeatedly(Return(false)); | |
| 1187 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1188 .WillRepeatedly(Return(false)); | |
| 1189 | |
| 1190 const char kVideoChannelName[] = "video"; | |
| 1191 InitSessionStats(kVideoChannelName); | |
| 1192 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1193 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 1194 Return(true))); | |
| 1195 | |
| 1196 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
| 1197 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
| 1198 nullptr, kVideoChannelName, false); | |
| 1199 AddIncomingVideoTrackStats(); | |
| 1200 stats.AddStream(stream_); | |
| 1201 | |
| 1202 // Constructs an ssrc stats update. | |
| 1203 cricket::VideoReceiverInfo video_receiver_info; | |
| 1204 cricket::VideoMediaInfo stats_read; | |
| 1205 const int64_t kNumOfPacketsConcealed = 54321; | |
| 1206 | |
| 1207 // Construct a stats value to read. | |
| 1208 video_receiver_info.add_ssrc(1234); | |
| 1209 video_receiver_info.packets_concealed = kNumOfPacketsConcealed; | |
| 1210 stats_read.receivers.push_back(video_receiver_info); | |
| 1211 | |
| 1212 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
| 1213 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
| 1214 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1215 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
| 1216 Return(true))); | |
| 1217 | |
| 1218 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1219 StatsReports reports; | |
| 1220 stats.GetStats(NULL, &reports); | |
| 1221 // |reports| should contain at least one session report, one track report, | |
| 1222 // and one ssrc report. | |
| 1223 EXPECT_LE(static_cast<size_t>(3), reports.size()); | |
| 1224 const StatsReport* track_report = FindNthReportByType( | |
| 1225 reports, StatsReport::kStatsReportTypeTrack, 1); | |
| 1226 EXPECT_TRUE(track_report); | |
| 1227 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
| 1228 | |
| 1229 std::string ssrc_id = ExtractSsrcStatsValue( | |
| 1230 reports, StatsReport::kStatsValueNameSsrc); | |
| 1231 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
| 1232 | |
| 1233 std::string track_id = ExtractSsrcStatsValue( | |
| 1234 reports, StatsReport::kStatsValueNameTrackId); | |
| 1235 EXPECT_EQ(kRemoteTrackId, track_id); | |
| 1236 } | |
| 1237 | |
| 1238 // This test verifies the Ice Candidate report should contain the correct | |
| 1239 // information from local/remote candidates. | |
| 1240 TEST_F(StatsCollectorTest, IceCandidateReport) { | |
| 1241 StatsCollectorForTest stats(&pc_); | |
| 1242 | |
| 1243 StatsReports reports; // returned values. | |
| 1244 | |
| 1245 const int local_port = 2000; | |
| 1246 const char local_ip[] = "192.168.0.1"; | |
| 1247 const int remote_port = 2001; | |
| 1248 const char remote_ip[] = "192.168.0.2"; | |
| 1249 | |
| 1250 rtc::SocketAddress local_address(local_ip, local_port); | |
| 1251 rtc::SocketAddress remote_address(remote_ip, remote_port); | |
| 1252 rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; | |
| 1253 uint32_t priority = 1000; | |
| 1254 | |
| 1255 cricket::Candidate c; | |
| 1256 ASSERT(c.id().length() > 0); | |
| 1257 c.set_type(cricket::LOCAL_PORT_TYPE); | |
| 1258 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
| 1259 c.set_address(local_address); | |
| 1260 c.set_priority(priority); | |
| 1261 c.set_network_type(network_type); | |
| 1262 std::string report_id = AddCandidateReport(&stats, c, true)->id()->ToString(); | |
| 1263 EXPECT_EQ("Cand-" + c.id(), report_id); | |
| 1264 | |
| 1265 c = cricket::Candidate(); | |
| 1266 ASSERT(c.id().length() > 0); | |
| 1267 c.set_type(cricket::PRFLX_PORT_TYPE); | |
| 1268 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
| 1269 c.set_address(remote_address); | |
| 1270 c.set_priority(priority); | |
| 1271 c.set_network_type(network_type); | |
| 1272 report_id = AddCandidateReport(&stats, c, false)->id()->ToString(); | |
| 1273 EXPECT_EQ("Cand-" + c.id(), report_id); | |
| 1274 | |
| 1275 stats.GetStats(NULL, &reports); | |
| 1276 | |
| 1277 // Verify the local candidate report is populated correctly. | |
| 1278 EXPECT_EQ( | |
| 1279 local_ip, | |
| 1280 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1281 StatsReport::kStatsValueNameCandidateIPAddress)); | |
| 1282 EXPECT_EQ( | |
| 1283 rtc::ToString<int>(local_port), | |
| 1284 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1285 StatsReport::kStatsValueNameCandidatePortNumber)); | |
| 1286 EXPECT_EQ( | |
| 1287 cricket::UDP_PROTOCOL_NAME, | |
| 1288 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1289 StatsReport::kStatsValueNameCandidateTransportType)); | |
| 1290 EXPECT_EQ( | |
| 1291 rtc::ToString<int>(priority), | |
| 1292 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1293 StatsReport::kStatsValueNameCandidatePriority)); | |
| 1294 EXPECT_EQ( | |
| 1295 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), | |
| 1296 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1297 StatsReport::kStatsValueNameCandidateType)); | |
| 1298 EXPECT_EQ( | |
| 1299 AdapterTypeToStatsType(network_type), | |
| 1300 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
| 1301 StatsReport::kStatsValueNameCandidateNetworkType)); | |
| 1302 | |
| 1303 // Verify the remote candidate report is populated correctly. | |
| 1304 EXPECT_EQ(remote_ip, | |
| 1305 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
| 1306 reports, | |
| 1307 StatsReport::kStatsValueNameCandidateIPAddress)); | |
| 1308 EXPECT_EQ(rtc::ToString<int>(remote_port), | |
| 1309 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
| 1310 reports, | |
| 1311 StatsReport::kStatsValueNameCandidatePortNumber)); | |
| 1312 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, | |
| 1313 ExtractStatsValue( | |
| 1314 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
| 1315 StatsReport::kStatsValueNameCandidateTransportType)); | |
| 1316 EXPECT_EQ(rtc::ToString<int>(priority), | |
| 1317 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
| 1318 reports, | |
| 1319 StatsReport::kStatsValueNameCandidatePriority)); | |
| 1320 EXPECT_EQ( | |
| 1321 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), | |
| 1322 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
| 1323 reports, StatsReport::kStatsValueNameCandidateType)); | |
| 1324 EXPECT_EQ(kNotFound, | |
| 1325 ExtractStatsValue( | |
| 1326 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
| 1327 StatsReport::kStatsValueNameCandidateNetworkType)); | |
| 1328 } | |
| 1329 | |
| 1330 // This test verifies that all chained certificates are correctly | |
| 1331 // reported | |
| 1332 TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { | |
| 1333 // Build local certificate chain. | |
| 1334 std::vector<std::string> local_ders(5); | |
| 1335 local_ders[0] = "These"; | |
| 1336 local_ders[1] = "are"; | |
| 1337 local_ders[2] = "some"; | |
| 1338 local_ders[3] = "der"; | |
| 1339 local_ders[4] = "values"; | |
| 1340 rtc::FakeSSLCertificate local_cert(DersToPems(local_ders)); | |
| 1341 | |
| 1342 // Build remote certificate chain | |
| 1343 std::vector<std::string> remote_ders(4); | |
| 1344 remote_ders[0] = "A"; | |
| 1345 remote_ders[1] = "non-"; | |
| 1346 remote_ders[2] = "intersecting"; | |
| 1347 remote_ders[3] = "set"; | |
| 1348 rtc::FakeSSLCertificate remote_cert(DersToPems(remote_ders)); | |
| 1349 | |
| 1350 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders); | |
| 1351 } | |
| 1352 | |
| 1353 // This test verifies that all certificates without chains are correctly | |
| 1354 // reported. | |
| 1355 TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { | |
| 1356 // Build local certificate. | |
| 1357 std::string local_der = "This is the local der."; | |
| 1358 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
| 1359 | |
| 1360 // Build remote certificate. | |
| 1361 std::string remote_der = "This is somebody else's der."; | |
| 1362 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
| 1363 | |
| 1364 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
| 1365 remote_cert, std::vector<std::string>(1, remote_der)); | |
| 1366 } | |
| 1367 | |
| 1368 // This test verifies that the stats are generated correctly when no | |
| 1369 // transport is present. | |
| 1370 TEST_F(StatsCollectorTest, NoTransport) { | |
| 1371 StatsCollectorForTest stats(&pc_); | |
| 1372 | |
| 1373 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1374 .WillRepeatedly(Return(false)); | |
| 1375 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1376 .WillRepeatedly(Return(false)); | |
| 1377 | |
| 1378 StatsReports reports; // returned values. | |
| 1379 | |
| 1380 // Fake stats to process. | |
| 1381 cricket::TransportChannelStats channel_stats; | |
| 1382 channel_stats.component = 1; | |
| 1383 | |
| 1384 cricket::TransportStats transport_stats; | |
| 1385 transport_stats.transport_name = "audio"; | |
| 1386 transport_stats.channel_stats.push_back(channel_stats); | |
| 1387 | |
| 1388 SessionStats session_stats; | |
| 1389 session_stats.transport_stats[transport_stats.transport_name] = | |
| 1390 transport_stats; | |
| 1391 | |
| 1392 // Configure MockWebRtcSession | |
| 1393 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1394 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
| 1395 Return(true))); | |
| 1396 | |
| 1397 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1398 stats.GetStats(NULL, &reports); | |
| 1399 | |
| 1400 // Check that the local certificate is absent. | |
| 1401 std::string local_certificate_id = ExtractStatsValue( | |
| 1402 StatsReport::kStatsReportTypeComponent, | |
| 1403 reports, | |
| 1404 StatsReport::kStatsValueNameLocalCertificateId); | |
| 1405 ASSERT_EQ(kNotFound, local_certificate_id); | |
| 1406 | |
| 1407 // Check that the remote certificate is absent. | |
| 1408 std::string remote_certificate_id = ExtractStatsValue( | |
| 1409 StatsReport::kStatsReportTypeComponent, | |
| 1410 reports, | |
| 1411 StatsReport::kStatsValueNameRemoteCertificateId); | |
| 1412 ASSERT_EQ(kNotFound, remote_certificate_id); | |
| 1413 | |
| 1414 // Check that the negotiated ciphers are absent. | |
| 1415 std::string dtls_cipher_suite = | |
| 1416 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
| 1417 StatsReport::kStatsValueNameDtlsCipher); | |
| 1418 ASSERT_EQ(kNotFound, dtls_cipher_suite); | |
| 1419 std::string srtp_crypto_suite = | |
| 1420 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
| 1421 StatsReport::kStatsValueNameSrtpCipher); | |
| 1422 ASSERT_EQ(kNotFound, srtp_crypto_suite); | |
| 1423 } | |
| 1424 | |
| 1425 // This test verifies that the stats are generated correctly when the transport | |
| 1426 // does not have any certificates. | |
| 1427 TEST_F(StatsCollectorTest, NoCertificates) { | |
| 1428 StatsCollectorForTest stats(&pc_); | |
| 1429 | |
| 1430 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1431 .WillRepeatedly(Return(false)); | |
| 1432 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1433 .WillRepeatedly(Return(false)); | |
| 1434 | |
| 1435 StatsReports reports; // returned values. | |
| 1436 | |
| 1437 // Fake stats to process. | |
| 1438 cricket::TransportChannelStats channel_stats; | |
| 1439 channel_stats.component = 1; | |
| 1440 | |
| 1441 cricket::TransportStats transport_stats; | |
| 1442 transport_stats.transport_name = "audio"; | |
| 1443 transport_stats.channel_stats.push_back(channel_stats); | |
| 1444 | |
| 1445 SessionStats session_stats; | |
| 1446 session_stats.transport_stats[transport_stats.transport_name] = | |
| 1447 transport_stats; | |
| 1448 | |
| 1449 // Fake transport object. | |
| 1450 rtc::scoped_ptr<cricket::FakeTransport> transport( | |
| 1451 new cricket::FakeTransport(transport_stats.transport_name)); | |
| 1452 | |
| 1453 // Configure MockWebRtcSession | |
| 1454 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1455 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
| 1456 Return(true))); | |
| 1457 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1458 stats.GetStats(NULL, &reports); | |
| 1459 | |
| 1460 // Check that the local certificate is absent. | |
| 1461 std::string local_certificate_id = ExtractStatsValue( | |
| 1462 StatsReport::kStatsReportTypeComponent, | |
| 1463 reports, | |
| 1464 StatsReport::kStatsValueNameLocalCertificateId); | |
| 1465 ASSERT_EQ(kNotFound, local_certificate_id); | |
| 1466 | |
| 1467 // Check that the remote certificate is absent. | |
| 1468 std::string remote_certificate_id = ExtractStatsValue( | |
| 1469 StatsReport::kStatsReportTypeComponent, | |
| 1470 reports, | |
| 1471 StatsReport::kStatsValueNameRemoteCertificateId); | |
| 1472 ASSERT_EQ(kNotFound, remote_certificate_id); | |
| 1473 } | |
| 1474 | |
| 1475 // This test verifies that a remote certificate with an unsupported digest | |
| 1476 // algorithm is correctly ignored. | |
| 1477 TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { | |
| 1478 // Build a local certificate. | |
| 1479 std::string local_der = "This is the local der."; | |
| 1480 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
| 1481 | |
| 1482 // Build a remote certificate with an unsupported digest algorithm. | |
| 1483 std::string remote_der = "This is somebody else's der."; | |
| 1484 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
| 1485 remote_cert.set_digest_algorithm("foobar"); | |
| 1486 | |
| 1487 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
| 1488 remote_cert, std::vector<std::string>()); | |
| 1489 } | |
| 1490 | |
| 1491 // This test verifies that a local stats object can get statistics via | |
| 1492 // AudioTrackInterface::GetStats() method. | |
| 1493 TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) { | |
| 1494 StatsCollectorForTest stats(&pc_); | |
| 1495 | |
| 1496 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1497 .WillRepeatedly(Return(false)); | |
| 1498 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1499 .WillRepeatedly(Return(false)); | |
| 1500 | |
| 1501 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
| 1502 // The transport_name known by the voice channel. | |
| 1503 const std::string kVcName("vcname"); | |
| 1504 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
| 1505 media_channel, nullptr, kVcName, false); | |
| 1506 AddOutgoingAudioTrackStats(); | |
| 1507 stats.AddStream(stream_); | |
| 1508 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
| 1509 | |
| 1510 cricket::VoiceSenderInfo voice_sender_info; | |
| 1511 InitVoiceSenderInfo(&voice_sender_info); | |
| 1512 | |
| 1513 cricket::VoiceMediaInfo stats_read; | |
| 1514 StatsReports reports; // returned values. | |
| 1515 SetupAndVerifyAudioTrackStats( | |
| 1516 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
| 1517 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
| 1518 | |
| 1519 // Verify that there is no remote report for the local audio track because | |
| 1520 // we did not set it up. | |
| 1521 const StatsReport* remote_report = FindNthReportByType(reports, | |
| 1522 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
| 1523 EXPECT_TRUE(remote_report == NULL); | |
| 1524 } | |
| 1525 | |
| 1526 // This test verifies that audio receive streams populate stats reports | |
| 1527 // correctly. | |
| 1528 TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { | |
| 1529 StatsCollectorForTest stats(&pc_); | |
| 1530 | |
| 1531 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1532 .WillRepeatedly(Return(false)); | |
| 1533 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1534 .WillRepeatedly(Return(false)); | |
| 1535 | |
| 1536 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
| 1537 // The transport_name known by the voice channel. | |
| 1538 const std::string kVcName("vcname"); | |
| 1539 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
| 1540 media_channel, nullptr, kVcName, false); | |
| 1541 AddIncomingAudioTrackStats(); | |
| 1542 stats.AddStream(stream_); | |
| 1543 | |
| 1544 cricket::VoiceReceiverInfo voice_receiver_info; | |
| 1545 InitVoiceReceiverInfo(&voice_receiver_info); | |
| 1546 voice_receiver_info.codec_name = "fake_codec"; | |
| 1547 | |
| 1548 cricket::VoiceMediaInfo stats_read; | |
| 1549 StatsReports reports; // returned values. | |
| 1550 SetupAndVerifyAudioTrackStats( | |
| 1551 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
| 1552 media_channel, NULL, &voice_receiver_info, &stats_read, &reports); | |
| 1553 } | |
| 1554 | |
| 1555 // This test verifies that a local stats object won't update its statistics | |
| 1556 // after a RemoveLocalAudioTrack() call. | |
| 1557 TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) { | |
| 1558 StatsCollectorForTest stats(&pc_); | |
| 1559 | |
| 1560 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1561 .WillRepeatedly(Return(false)); | |
| 1562 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1563 .WillRepeatedly(Return(false)); | |
| 1564 | |
| 1565 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
| 1566 // The transport_name known by the voice channel. | |
| 1567 const std::string kVcName("vcname"); | |
| 1568 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
| 1569 media_channel, nullptr, kVcName, false); | |
| 1570 AddOutgoingAudioTrackStats(); | |
| 1571 stats.AddStream(stream_); | |
| 1572 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
| 1573 | |
| 1574 // Instruct the session to return stats containing the transport channel. | |
| 1575 InitSessionStats(kVcName); | |
| 1576 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1577 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 1578 Return(true))); | |
| 1579 | |
| 1580 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
| 1581 cricket::VoiceSenderInfo voice_sender_info; | |
| 1582 InitVoiceSenderInfo(&voice_sender_info); | |
| 1583 | |
| 1584 // Constructs an ssrc stats update. | |
| 1585 cricket::VoiceMediaInfo stats_read; | |
| 1586 stats_read.senders.push_back(voice_sender_info); | |
| 1587 | |
| 1588 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
| 1589 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
| 1590 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1591 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
| 1592 Return(true))); | |
| 1593 | |
| 1594 StatsReports reports; // returned values. | |
| 1595 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1596 stats.GetStats(NULL, &reports); | |
| 1597 | |
| 1598 // The report will exist since we don't remove them in RemoveStream(). | |
| 1599 const StatsReport* report = FindNthReportByType( | |
| 1600 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
| 1601 EXPECT_FALSE(report == NULL); | |
| 1602 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
| 1603 std::string track_id = ExtractSsrcStatsValue( | |
| 1604 reports, StatsReport::kStatsValueNameTrackId); | |
| 1605 EXPECT_EQ(kLocalTrackId, track_id); | |
| 1606 std::string ssrc_id = ExtractSsrcStatsValue( | |
| 1607 reports, StatsReport::kStatsValueNameSsrc); | |
| 1608 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
| 1609 | |
| 1610 // Verifies the values in the track report, no value will be changed by the | |
| 1611 // AudioTrackInterface::GetSignalValue() and | |
| 1612 // AudioProcessorInterface::AudioProcessorStats::GetStats(); | |
| 1613 VerifyVoiceSenderInfoReport(report, voice_sender_info); | |
| 1614 } | |
| 1615 | |
| 1616 // This test verifies that when ongoing and incoming audio tracks are using | |
| 1617 // the same ssrc, they populate stats reports correctly. | |
| 1618 TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { | |
| 1619 StatsCollectorForTest stats(&pc_); | |
| 1620 | |
| 1621 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1622 .WillRepeatedly(Return(false)); | |
| 1623 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1624 .WillRepeatedly(Return(false)); | |
| 1625 | |
| 1626 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
| 1627 // The transport_name known by the voice channel. | |
| 1628 const std::string kVcName("vcname"); | |
| 1629 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
| 1630 media_channel, nullptr, kVcName, false); | |
| 1631 | |
| 1632 // Create a local stream with a local audio track and adds it to the stats. | |
| 1633 AddOutgoingAudioTrackStats(); | |
| 1634 stats.AddStream(stream_); | |
| 1635 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
| 1636 | |
| 1637 // Create a remote stream with a remote audio track and adds it to the stats. | |
| 1638 rtc::scoped_refptr<webrtc::MediaStream> remote_stream( | |
| 1639 webrtc::MediaStream::Create("remotestreamlabel")); | |
| 1640 rtc::scoped_refptr<FakeAudioTrack> remote_track( | |
| 1641 new rtc::RefCountedObject<FakeAudioTrack>(kRemoteTrackId)); | |
| 1642 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) | |
| 1643 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); | |
| 1644 remote_stream->AddTrack(remote_track); | |
| 1645 stats.AddStream(remote_stream); | |
| 1646 | |
| 1647 // Instruct the session to return stats containing the transport channel. | |
| 1648 InitSessionStats(kVcName); | |
| 1649 EXPECT_CALL(session_, GetTransportStats(_)) | |
| 1650 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
| 1651 Return(true))); | |
| 1652 | |
| 1653 cricket::VoiceSenderInfo voice_sender_info; | |
| 1654 InitVoiceSenderInfo(&voice_sender_info); | |
| 1655 | |
| 1656 // Some of the contents in |voice_sender_info| needs to be updated from the | |
| 1657 // |audio_track_|. | |
| 1658 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info); | |
| 1659 | |
| 1660 cricket::VoiceReceiverInfo voice_receiver_info; | |
| 1661 InitVoiceReceiverInfo(&voice_receiver_info); | |
| 1662 | |
| 1663 // Constructs an ssrc stats update. | |
| 1664 cricket::VoiceMediaInfo stats_read; | |
| 1665 stats_read.senders.push_back(voice_sender_info); | |
| 1666 stats_read.receivers.push_back(voice_receiver_info); | |
| 1667 | |
| 1668 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
| 1669 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
| 1670 EXPECT_CALL(*media_channel, GetStats(_)) | |
| 1671 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
| 1672 Return(true))); | |
| 1673 | |
| 1674 StatsReports reports; // returned values. | |
| 1675 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
| 1676 | |
| 1677 // Get stats for the local track. | |
| 1678 stats.GetStats(audio_track_.get(), &reports); | |
| 1679 const StatsReport* track_report = FindNthReportByType( | |
| 1680 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
| 1681 EXPECT_TRUE(track_report); | |
| 1682 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
| 1683 std::string track_id = ExtractSsrcStatsValue( | |
| 1684 reports, StatsReport::kStatsValueNameTrackId); | |
| 1685 EXPECT_EQ(kLocalTrackId, track_id); | |
| 1686 VerifyVoiceSenderInfoReport(track_report, voice_sender_info); | |
| 1687 | |
| 1688 // Get stats for the remote track. | |
| 1689 reports.clear(); | |
| 1690 stats.GetStats(remote_track.get(), &reports); | |
| 1691 track_report = FindNthReportByType(reports, | |
| 1692 StatsReport::kStatsReportTypeSsrc, 1); | |
| 1693 EXPECT_TRUE(track_report); | |
| 1694 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
| 1695 track_id = ExtractSsrcStatsValue(reports, | |
| 1696 StatsReport::kStatsValueNameTrackId); | |
| 1697 EXPECT_EQ(kRemoteTrackId, track_id); | |
| 1698 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info); | |
| 1699 } | |
| 1700 | |
| 1701 // This test verifies that when two outgoing audio tracks are using the same | |
| 1702 // ssrc at different times, they populate stats reports correctly. | |
| 1703 // TODO(xians): Figure out if it is possible to encapsulate the setup and | |
| 1704 // avoid duplication of code in test cases. | |
| 1705 TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { | |
| 1706 StatsCollectorForTest stats(&pc_); | |
| 1707 | |
| 1708 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
| 1709 .WillRepeatedly(Return(false)); | |
| 1710 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
| 1711 .WillRepeatedly(Return(false)); | |
| 1712 | |
| 1713 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
| 1714 // The transport_name known by the voice channel. | |
| 1715 const std::string kVcName("vcname"); | |
| 1716 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
| 1717 media_channel, nullptr, kVcName, false); | |
| 1718 | |
| 1719 // Create a local stream with a local audio track and adds it to the stats. | |
| 1720 AddOutgoingAudioTrackStats(); | |
| 1721 stats.AddStream(stream_); | |
| 1722 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
| 1723 | |
| 1724 cricket::VoiceSenderInfo voice_sender_info; | |
| 1725 voice_sender_info.add_ssrc(kSsrcOfTrack); | |
| 1726 | |
| 1727 cricket::VoiceMediaInfo stats_read; | |
| 1728 StatsReports reports; // returned values. | |
| 1729 SetupAndVerifyAudioTrackStats( | |
| 1730 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
| 1731 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
| 1732 | |
| 1733 // Remove the previous audio track from the stream. | |
| 1734 stream_->RemoveTrack(audio_track_.get()); | |
| 1735 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
| 1736 | |
| 1737 // Create a new audio track and adds it to the stream and stats. | |
| 1738 static const std::string kNewTrackId = "new_track_id"; | |
| 1739 rtc::scoped_refptr<FakeAudioTrack> new_audio_track( | |
| 1740 new rtc::RefCountedObject<FakeAudioTrack>(kNewTrackId)); | |
| 1741 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) | |
| 1742 .WillOnce(DoAll(SetArgPointee<1>(kNewTrackId), Return(true))); | |
| 1743 stream_->AddTrack(new_audio_track); | |
| 1744 | |
| 1745 stats.AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); | |
| 1746 stats.ClearUpdateStatsCacheForTest(); | |
| 1747 cricket::VoiceSenderInfo new_voice_sender_info; | |
| 1748 InitVoiceSenderInfo(&new_voice_sender_info); | |
| 1749 cricket::VoiceMediaInfo new_stats_read; | |
| 1750 reports.clear(); | |
| 1751 SetupAndVerifyAudioTrackStats( | |
| 1752 new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
| 1753 media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); | |
| 1754 } | |
| 1755 | |
| 1756 } // namespace webrtc | |
| OLD | NEW |