• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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:
MockWebRtcSession(webrtc::MediaControllerInterface * media_controller)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:
MockPeerConnection()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:
MockVideoMediaChannel()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:
MockVoiceMediaChannel()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:
FakeAudioProcessor()137   FakeAudioProcessor() {}
~FakeAudioProcessor()138   ~FakeAudioProcessor() {}
139 
140  private:
GetStats(AudioProcessorInterface::AudioProcessorStats * stats)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:
FakeAudioTrack(const std::string & id)154   explicit FakeAudioTrack(const std::string& id)
155       : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id),
156         processor_(new rtc::RefCountedObject<FakeAudioProcessor>()) {}
kind() const157   std::string kind() const override { return "audio"; }
GetSource() const158   webrtc::AudioSourceInterface* GetSource() const override { return NULL; }
AddSink(webrtc::AudioTrackSinkInterface * sink)159   void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
RemoveSink(webrtc::AudioTrackSinkInterface * sink)160   void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)161   bool GetSignalLevel(int* level) override {
162     *level = 1;
163     return true;
164   }
GetAudioProcessor()165   rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor()
166       override {
167     return processor_;
168   }
169 
170  private:
171   rtc::scoped_refptr<FakeAudioProcessor> processor_;
172 };
173 
GetValue(const StatsReport * report,StatsReport::StatsValueName name,std::string * value)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 
ExtractStatsValue(const StatsReport::StatsType & type,const StatsReports & reports,StatsReport::StatsValueName name)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 
TypedIdFromIdString(StatsReport::StatsType type,const std::string & value)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 
IdFromCertIdString(const std::string & cert_id)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.
FindNthReportByType(const StatsReports & reports,const StatsReport::StatsType & type,int n)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 
FindReportById(const StatsReports & reports,const StatsReport::Id & id)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 
ExtractSsrcStatsValue(StatsReports reports,StatsReport::StatsValueName name)243 std::string ExtractSsrcStatsValue(StatsReports reports,
244                                   StatsReport::StatsValueName name) {
245   return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name);
246 }
247 
ExtractBweStatsValue(StatsReports reports,StatsReport::StatsValueName name)248 std::string ExtractBweStatsValue(StatsReports reports,
249                                  StatsReport::StatsValueName name) {
250   return ExtractStatsValue(
251       StatsReport::kStatsReportTypeBwe, reports, name);
252 }
253 
DerToPem(const std::string & der)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 
DersToPems(const std::vector<std::string> & ders)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 
CheckCertChainReports(const StatsReports & reports,const std::vector<std::string> & ders,const StatsReport::Id & start_id)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 
VerifyVoiceReceiverInfoReport(const StatsReport * report,const cricket::VoiceReceiverInfo & info)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 
VerifyVoiceSenderInfoReport(const StatsReport * report,const cricket::VoiceSenderInfo & sinfo)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.
InitVoiceSenderInfo(cricket::VoiceSenderInfo * voice_sender_info)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 
UpdateVoiceSenderInfoFromAudioTrack(FakeAudioTrack * audio_track,cricket::VoiceSenderInfo * voice_sender_info)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 
InitVoiceReceiverInfo(cricket::VoiceReceiverInfo * voice_receiver_info)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:
StatsCollectorForTest(PeerConnection * pc)491   explicit StatsCollectorForTest(PeerConnection* pc)
492       : StatsCollector(pc), time_now_(19477) {}
493 
GetTimeNow()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:
StatsCollectorTest()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 
~StatsCollectorTest()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.
InitSessionStats(const std::string & vc_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.
AddOutgoingVideoTrackStats()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.
AddIncomingVideoTrackStats()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.
AddOutgoingAudioTrackStats()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.
AddIncomingAudioTrackStats()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 
AddDataChannel(cricket::DataChannelType type,const std::string & label,int id)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 
AddCandidateReport(StatsCollector * collector,const cricket::Candidate & candidate,bool local)591   StatsReport* AddCandidateReport(StatsCollector* collector,
592                                   const cricket::Candidate& candidate,
593                                   bool local) {
594     return collector->AddCandidateReport(candidate, local);
595   }
596 
SetupAndVerifyAudioTrackStats(FakeAudioTrack * audio_track,webrtc::MediaStream * stream,webrtc::StatsCollector * stats,cricket::VoiceChannel * voice_channel,const std::string & vc_name,MockVoiceMediaChannel * media_channel,cricket::VoiceSenderInfo * voice_sender_info,cricket::VoiceReceiverInfo * voice_receiver_info,cricket::VoiceMediaInfo * stats_read,StatsReports * reports)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 
TestCertificateReports(const rtc::FakeSSLCertificate & local_cert,const std::vector<std::string> & local_ders,const rtc::FakeSSLCertificate & remote_cert,const std::vector<std::string> & remote_ders)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.
TEST_F(StatsCollectorTest,ExtractDataInfo)775 TEST_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.
TEST_F(StatsCollectorTest,BytesCounterHandles64Bits)813 TEST_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.
TEST_F(StatsCollectorTest,BandwidthEstimationInfoIsReported)859 TEST_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.
TEST_F(StatsCollectorTest,SessionObjectExists)916 TEST_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.
TEST_F(StatsCollectorTest,OnlyOneSessionObjectExists)929 TEST_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.
TEST_F(StatsCollectorTest,TrackObjectExistsWithoutUpdateStats)946 TEST_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.
TEST_F(StatsCollectorTest,TrackAndSsrcObjectExistAfterUpdateSsrcStats)971 TEST_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.
TEST_F(StatsCollectorTest,TransportObjectLinkedFromSsrcObject)1039 TEST_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.
TEST_F(StatsCollectorTest,RemoteSsrcInfoIsAbsent)1102 TEST_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.
TEST_F(StatsCollectorTest,RemoteSsrcInfoIsPresent)1123 TEST_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.
TEST_F(StatsCollectorTest,ReportsFromRemoteTrack)1174 TEST_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.
TEST_F(StatsCollectorTest,IceCandidateReport)1232 TEST_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
TEST_F(StatsCollectorTest,ChainedCertificateReportsCreated)1324 TEST_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.
TEST_F(StatsCollectorTest,ChainlessCertificateReportsCreated)1347 TEST_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.
TEST_F(StatsCollectorTest,NoTransport)1362 TEST_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.
TEST_F(StatsCollectorTest,NoCertificates)1419 TEST_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.
TEST_F(StatsCollectorTest,UnsupportedDigestIgnored)1469 TEST_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.
TEST_F(StatsCollectorTest,GetStatsFromLocalAudioTrack)1485 TEST_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.
TEST_F(StatsCollectorTest,GetStatsFromRemoteStream)1520 TEST_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.
TEST_F(StatsCollectorTest,GetStatsAfterRemoveAudioStream)1549 TEST_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.
TEST_F(StatsCollectorTest,LocalAndRemoteTracksWithSameSsrc)1610 TEST_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.
TEST_F(StatsCollectorTest,TwoLocalTracksWithSameSsrc)1697 TEST_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