xref: /aosp_15_r20/external/webrtc/pc/legacy_stats_collector_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/legacy_stats_collector.h"
12 
13 #include <stdio.h>
14 
15 #include <cstdint>
16 
17 #include "absl/algorithm/container.h"
18 #include "absl/types/optional.h"
19 #include "api/audio_codecs/audio_encoder.h"
20 #include "api/candidate.h"
21 #include "api/data_channel_interface.h"
22 #include "api/media_stream_track.h"
23 #include "api/media_types.h"
24 #include "api/rtp_sender_interface.h"
25 #include "api/scoped_refptr.h"
26 #include "call/call.h"
27 #include "media/base/media_channel.h"
28 #include "modules/audio_processing/include/audio_processing_statistics.h"
29 #include "p2p/base/ice_transport_internal.h"
30 #include "pc/media_stream.h"
31 #include "pc/rtp_receiver.h"
32 #include "pc/rtp_sender.h"
33 #include "pc/sctp_data_channel.h"
34 #include "pc/test/fake_peer_connection_for_stats.h"
35 #include "pc/test/fake_video_track_source.h"
36 #include "pc/test/mock_rtp_receiver_internal.h"
37 #include "pc/test/mock_rtp_sender_internal.h"
38 #include "pc/transport_stats.h"
39 #include "pc/video_track.h"
40 #include "rtc_base/fake_ssl_identity.h"
41 #include "rtc_base/message_digest.h"
42 #include "rtc_base/net_helper.h"
43 #include "rtc_base/rtc_certificate.h"
44 #include "rtc_base/socket_address.h"
45 #include "rtc_base/ssl_identity.h"
46 #include "rtc_base/ssl_stream_adapter.h"
47 #include "rtc_base/string_encode.h"
48 #include "rtc_base/third_party/base64/base64.h"
49 #include "rtc_base/thread.h"
50 #include "test/gmock.h"
51 #include "test/gtest.h"
52 
53 using cricket::ConnectionInfo;
54 using cricket::SsrcReceiverInfo;
55 using cricket::TransportChannelStats;
56 using cricket::VideoMediaInfo;
57 using cricket::VideoReceiverInfo;
58 using cricket::VideoSenderInfo;
59 using cricket::VoiceMediaInfo;
60 using cricket::VoiceReceiverInfo;
61 using cricket::VoiceSenderInfo;
62 using ::testing::_;
63 using ::testing::AtMost;
64 using ::testing::Return;
65 using ::testing::UnorderedElementsAre;
66 
67 namespace webrtc {
68 
69 namespace internal {
70 // This value comes from openssl/tls1.h
71 static const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
72 }  // namespace internal
73 
74 // Error return values
75 const char kNotFound[] = "NOT FOUND";
76 
77 // Constant names for track identification.
78 const char kLocalTrackId[] = "local_track_id";
79 const char kRemoteTrackId[] = "remote_track_id";
80 const uint32_t kSsrcOfTrack = 1234;
81 
82 class FakeAudioProcessor : public AudioProcessorInterface {
83  public:
FakeAudioProcessor()84   FakeAudioProcessor() {}
~FakeAudioProcessor()85   ~FakeAudioProcessor() {}
86 
87  private:
GetStats(bool has_recv_streams)88   AudioProcessorInterface::AudioProcessorStatistics GetStats(
89       bool has_recv_streams) override {
90     AudioProcessorStatistics stats;
91     if (has_recv_streams) {
92       stats.apm_statistics.echo_return_loss = 2.0;
93       stats.apm_statistics.echo_return_loss_enhancement = 3.0;
94       stats.apm_statistics.delay_median_ms = 4;
95       stats.apm_statistics.delay_standard_deviation_ms = 5;
96     }
97     return stats;
98   }
99 };
100 
101 class FakeAudioTrack : public MediaStreamTrack<AudioTrackInterface> {
102  public:
FakeAudioTrack(const std::string & id)103   explicit FakeAudioTrack(const std::string& id)
104       : MediaStreamTrack<AudioTrackInterface>(id),
105         processor_(rtc::make_ref_counted<FakeAudioProcessor>()) {}
kind() const106   std::string kind() const override { return "audio"; }
GetSource() const107   AudioSourceInterface* GetSource() const override { return NULL; }
AddSink(AudioTrackSinkInterface * sink)108   void AddSink(AudioTrackSinkInterface* sink) override {}
RemoveSink(AudioTrackSinkInterface * sink)109   void RemoveSink(AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)110   bool GetSignalLevel(int* level) override {
111     *level = 1;
112     return true;
113   }
GetAudioProcessor()114   rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
115     return processor_;
116   }
117 
118  private:
119   rtc::scoped_refptr<FakeAudioProcessor> processor_;
120 };
121 
122 // This fake audio processor is used to verify that the undesired initial values
123 // (-1) will be filtered out.
124 class FakeAudioProcessorWithInitValue : public AudioProcessorInterface {
125  public:
FakeAudioProcessorWithInitValue()126   FakeAudioProcessorWithInitValue() {}
~FakeAudioProcessorWithInitValue()127   ~FakeAudioProcessorWithInitValue() {}
128 
129  private:
GetStats(bool)130   AudioProcessorInterface::AudioProcessorStatistics GetStats(
131       bool /*has_recv_streams*/) override {
132     AudioProcessorStatistics stats;
133     return stats;
134   }
135 };
136 
137 class FakeAudioTrackWithInitValue
138     : public MediaStreamTrack<AudioTrackInterface> {
139  public:
FakeAudioTrackWithInitValue(const std::string & id)140   explicit FakeAudioTrackWithInitValue(const std::string& id)
141       : MediaStreamTrack<AudioTrackInterface>(id),
142         processor_(rtc::make_ref_counted<FakeAudioProcessorWithInitValue>()) {}
kind() const143   std::string kind() const override { return "audio"; }
GetSource() const144   AudioSourceInterface* GetSource() const override { return NULL; }
AddSink(AudioTrackSinkInterface * sink)145   void AddSink(AudioTrackSinkInterface* sink) override {}
RemoveSink(AudioTrackSinkInterface * sink)146   void RemoveSink(AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)147   bool GetSignalLevel(int* level) override {
148     *level = 1;
149     return true;
150   }
GetAudioProcessor()151   rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
152     return processor_;
153   }
154 
155  private:
156   rtc::scoped_refptr<FakeAudioProcessorWithInitValue> processor_;
157 };
158 
GetValue(const StatsReport * report,StatsReport::StatsValueName name,std::string * value)159 bool GetValue(const StatsReport* report,
160               StatsReport::StatsValueName name,
161               std::string* value) {
162   const StatsReport::Value* v = report->FindValue(name);
163   if (!v)
164     return false;
165   *value = v->ToString();
166   return true;
167 }
168 
ExtractStatsValue(const StatsReport::StatsType & type,const StatsReports & reports,StatsReport::StatsValueName name)169 std::string ExtractStatsValue(const StatsReport::StatsType& type,
170                               const StatsReports& reports,
171                               StatsReport::StatsValueName name) {
172   for (const auto* r : reports) {
173     std::string ret;
174     if (r->type() == type && GetValue(r, name, &ret))
175       return ret;
176   }
177 
178   return kNotFound;
179 }
180 
TypedIdFromIdString(StatsReport::StatsType type,const std::string & value)181 StatsReport::Id TypedIdFromIdString(StatsReport::StatsType type,
182                                     const std::string& value) {
183   EXPECT_FALSE(value.empty());
184   StatsReport::Id id;
185   if (value.empty())
186     return id;
187 
188   // This has assumptions about how the ID is constructed.  As is, this is
189   // OK since this is for testing purposes only, but if we ever need this
190   // in production, we should add a generic method that does this.
191   size_t index = value.find('_');
192   EXPECT_NE(index, std::string::npos);
193   if (index == std::string::npos || index == (value.length() - 1))
194     return id;
195 
196   id = StatsReport::NewTypedId(type, value.substr(index + 1));
197   EXPECT_EQ(id->ToString(), value);
198   return id;
199 }
200 
IdFromCertIdString(const std::string & cert_id)201 StatsReport::Id IdFromCertIdString(const std::string& cert_id) {
202   return TypedIdFromIdString(StatsReport::kStatsReportTypeCertificate, cert_id);
203 }
204 
205 // Finds the `n`-th report of type `type` in `reports`.
206 // `n` starts from 1 for finding the first report.
FindNthReportByType(const StatsReports & reports,const StatsReport::StatsType & type,int n)207 const StatsReport* FindNthReportByType(const StatsReports& reports,
208                                        const StatsReport::StatsType& type,
209                                        int n) {
210   for (size_t i = 0; i < reports.size(); ++i) {
211     if (reports[i]->type() == type) {
212       n--;
213       if (n == 0)
214         return reports[i];
215     }
216   }
217   return nullptr;
218 }
219 
220 // Returns the value of the stat identified by `name` in the `n`-th report of
221 // type `type` in `reports`.
222 // `n` starts from 1 for finding the first report.
223 // If either the `n`-th report is not found, or the stat is not present in that
224 // report, then nullopt is returned.
GetValueInNthReportByType(const StatsReports & reports,StatsReport::StatsType type,StatsReport::StatsValueName name,int n)225 absl::optional<std::string> GetValueInNthReportByType(
226     const StatsReports& reports,
227     StatsReport::StatsType type,
228     StatsReport::StatsValueName name,
229     int n) {
230   const StatsReport* report = FindNthReportByType(reports, type, n);
231   if (!report) {
232     return absl::nullopt;
233   }
234   std::string value;
235   if (!GetValue(report, name, &value)) {
236     return absl::nullopt;
237   }
238   return value;
239 }
240 
GetReportsByType(const StatsReports & reports,StatsReport::StatsType type)241 std::vector<const StatsReport*> GetReportsByType(const StatsReports& reports,
242                                                  StatsReport::StatsType type) {
243   std::vector<const StatsReport*> filtered_reports;
244   for (const StatsReport* report : reports) {
245     if (report->type() == type) {
246       filtered_reports.push_back(report);
247     }
248   }
249   return filtered_reports;
250 }
251 
FindReportById(const StatsReports & reports,const StatsReport::Id & id)252 const StatsReport* FindReportById(const StatsReports& reports,
253                                   const StatsReport::Id& id) {
254   for (const auto* r : reports) {
255     if (r->id()->Equals(id))
256       return r;
257   }
258   return nullptr;
259 }
260 
ExtractSsrcStatsValue(const StatsReports & reports,StatsReport::StatsValueName name)261 std::string ExtractSsrcStatsValue(const StatsReports& reports,
262                                   StatsReport::StatsValueName name) {
263   return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name);
264 }
265 
ExtractBweStatsValue(const StatsReports & reports,StatsReport::StatsValueName name)266 std::string ExtractBweStatsValue(const StatsReports& reports,
267                                  StatsReport::StatsValueName name) {
268   return ExtractStatsValue(StatsReport::kStatsReportTypeBwe, reports, name);
269 }
270 
DerToPem(const std::string & der)271 std::string DerToPem(const std::string& der) {
272   return rtc::SSLIdentity::DerToPem(
273       rtc::kPemTypeCertificate,
274       reinterpret_cast<const unsigned char*>(der.c_str()), der.length());
275 }
276 
DersToPems(const std::vector<std::string> & ders)277 std::vector<std::string> DersToPems(const std::vector<std::string>& ders) {
278   std::vector<std::string> pems(ders.size());
279   absl::c_transform(ders, pems.begin(), DerToPem);
280   return pems;
281 }
282 
CheckCertChainReports(const StatsReports & reports,const std::vector<std::string> & ders,const StatsReport::Id & start_id)283 void CheckCertChainReports(const StatsReports& reports,
284                            const std::vector<std::string>& ders,
285                            const StatsReport::Id& start_id) {
286   StatsReport::Id cert_id;
287   const StatsReport::Id* certificate_id = &start_id;
288   size_t i = 0;
289   while (true) {
290     const StatsReport* report = FindReportById(reports, *certificate_id);
291     ASSERT_TRUE(report != NULL);
292 
293     std::string der_base64;
294     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDer, &der_base64));
295     std::string der = rtc::Base64::Decode(der_base64, rtc::Base64::DO_STRICT);
296     EXPECT_EQ(ders[i], der);
297 
298     std::string fingerprint_algorithm;
299     EXPECT_TRUE(GetValue(report,
300                          StatsReport::kStatsValueNameFingerprintAlgorithm,
301                          &fingerprint_algorithm));
302     // The digest algorithm for a FakeSSLCertificate is always SHA-1.
303     std::string sha_1_str = rtc::DIGEST_SHA_1;
304     EXPECT_EQ(sha_1_str, fingerprint_algorithm);
305 
306     std::string fingerprint;
307     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameFingerprint,
308                          &fingerprint));
309     EXPECT_FALSE(fingerprint.empty());
310 
311     ++i;
312     std::string issuer_id;
313     if (!GetValue(report, StatsReport::kStatsValueNameIssuerId, &issuer_id)) {
314       break;
315     }
316 
317     cert_id = IdFromCertIdString(issuer_id);
318     certificate_id = &cert_id;
319   }
320   EXPECT_EQ(ders.size(), i);
321 }
322 
VerifyVoiceReceiverInfoReport(const StatsReport * report,const cricket::VoiceReceiverInfo & info)323 void VerifyVoiceReceiverInfoReport(const StatsReport* report,
324                                    const cricket::VoiceReceiverInfo& info) {
325   std::string value_in_report;
326   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioOutputLevel,
327                        &value_in_report));
328   EXPECT_EQ(rtc::ToString(info.audio_level), value_in_report);
329   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesReceived,
330                        &value_in_report));
331   EXPECT_EQ(rtc::ToString(info.payload_bytes_rcvd +
332                           info.header_and_padding_bytes_rcvd),
333             value_in_report);
334   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
335                        &value_in_report));
336   EXPECT_EQ(rtc::ToString(info.jitter_ms), value_in_report);
337   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterBufferMs,
338                        &value_in_report));
339   EXPECT_EQ(rtc::ToString(info.jitter_buffer_ms), value_in_report);
340   EXPECT_TRUE(GetValue(report,
341                        StatsReport::kStatsValueNamePreferredJitterBufferMs,
342                        &value_in_report));
343   EXPECT_EQ(rtc::ToString(info.jitter_buffer_preferred_ms), value_in_report);
344   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCurrentDelayMs,
345                        &value_in_report));
346   EXPECT_EQ(rtc::ToString(info.delay_estimate_ms), value_in_report);
347   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameExpandRate,
348                        &value_in_report));
349   EXPECT_EQ(rtc::ToString(info.expand_rate), value_in_report);
350   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSpeechExpandRate,
351                        &value_in_report));
352   EXPECT_EQ(rtc::ToString(info.speech_expand_rate), value_in_report);
353   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate,
354                        &value_in_report));
355   EXPECT_EQ(rtc::ToString(info.accelerate_rate), value_in_report);
356   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate,
357                        &value_in_report));
358   EXPECT_EQ(rtc::ToString(info.preemptive_expand_rate), value_in_report);
359   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate,
360                        &value_in_report));
361   EXPECT_EQ(rtc::ToString(info.secondary_decoded_rate), value_in_report);
362   EXPECT_TRUE(GetValue(report,
363                        StatsReport::kStatsValueNameSecondaryDiscardedRate,
364                        &value_in_report));
365   EXPECT_EQ(rtc::ToString(info.secondary_discarded_rate), value_in_report);
366   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsReceived,
367                        &value_in_report));
368   EXPECT_EQ(rtc::ToString(info.packets_rcvd), value_in_report);
369   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTSG,
370                        &value_in_report));
371   EXPECT_EQ(rtc::ToString(info.decoding_calls_to_silence_generator),
372             value_in_report);
373   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTN,
374                        &value_in_report));
375   EXPECT_EQ(rtc::ToString(info.decoding_calls_to_neteq), value_in_report);
376   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingNormal,
377                        &value_in_report));
378   EXPECT_EQ(rtc::ToString(info.decoding_normal), value_in_report);
379   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLC,
380                        &value_in_report));
381   EXPECT_EQ(rtc::ToString(info.decoding_plc), value_in_report);
382   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCodecPLC,
383                        &value_in_report));
384   EXPECT_EQ(rtc::ToString(info.decoding_codec_plc), value_in_report);
385   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCNG,
386                        &value_in_report));
387   EXPECT_EQ(rtc::ToString(info.decoding_cng), value_in_report);
388   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLCCNG,
389                        &value_in_report));
390   EXPECT_EQ(rtc::ToString(info.decoding_plc_cng), value_in_report);
391   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingMutedOutput,
392                        &value_in_report));
393   EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report);
394   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
395                        &value_in_report));
396 }
397 
VerifyVoiceSenderInfoReport(const StatsReport * report,const cricket::VoiceSenderInfo & sinfo)398 void VerifyVoiceSenderInfoReport(const StatsReport* report,
399                                  const cricket::VoiceSenderInfo& sinfo) {
400   std::string value_in_report;
401   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
402                        &value_in_report));
403   EXPECT_EQ(sinfo.codec_name, value_in_report);
404   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesSent,
405                        &value_in_report));
406   EXPECT_EQ(rtc::ToString(sinfo.payload_bytes_sent +
407                           sinfo.header_and_padding_bytes_sent),
408             value_in_report);
409   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsSent,
410                        &value_in_report));
411   EXPECT_EQ(rtc::ToString(sinfo.packets_sent), value_in_report);
412   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
413                        &value_in_report));
414   EXPECT_EQ(rtc::ToString(sinfo.packets_lost), value_in_report);
415   EXPECT_TRUE(
416       GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
417   EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
418   EXPECT_TRUE(
419       GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
420   EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
421   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
422                        &value_in_report));
423   EXPECT_EQ(rtc::ToString(sinfo.jitter_ms), value_in_report);
424   if (sinfo.apm_statistics.delay_median_ms) {
425     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
426                          &value_in_report));
427     EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_median_ms),
428               value_in_report);
429   } else {
430     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
431                           &value_in_report));
432   }
433   if (sinfo.apm_statistics.delay_standard_deviation_ms) {
434     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
435                          &value_in_report));
436     EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_standard_deviation_ms),
437               value_in_report);
438   } else {
439     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
440                           &value_in_report));
441   }
442   if (sinfo.apm_statistics.echo_return_loss) {
443     EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
444                          &value_in_report));
445     EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss),
446               value_in_report);
447   } else {
448     EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
449                           &value_in_report));
450   }
451   if (sinfo.apm_statistics.echo_return_loss_enhancement) {
452     EXPECT_TRUE(GetValue(report,
453                          StatsReport::kStatsValueNameEchoReturnLossEnhancement,
454                          &value_in_report));
455     EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss_enhancement),
456               value_in_report);
457   } else {
458     EXPECT_FALSE(GetValue(report,
459                           StatsReport::kStatsValueNameEchoReturnLossEnhancement,
460                           &value_in_report));
461   }
462   if (sinfo.apm_statistics.residual_echo_likelihood) {
463     EXPECT_TRUE(GetValue(report,
464                          StatsReport::kStatsValueNameResidualEchoLikelihood,
465                          &value_in_report));
466     EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.residual_echo_likelihood),
467               value_in_report);
468   } else {
469     EXPECT_FALSE(GetValue(report,
470                           StatsReport::kStatsValueNameResidualEchoLikelihood,
471                           &value_in_report));
472   }
473   if (sinfo.apm_statistics.residual_echo_likelihood_recent_max) {
474     EXPECT_TRUE(GetValue(
475         report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
476         &value_in_report));
477     EXPECT_EQ(rtc::ToString(
478                   *sinfo.apm_statistics.residual_echo_likelihood_recent_max),
479               value_in_report);
480   } else {
481     EXPECT_FALSE(GetValue(
482         report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
483         &value_in_report));
484   }
485   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
486                        &value_in_report));
487   EXPECT_EQ(rtc::ToString(sinfo.audio_level), value_in_report);
488   EXPECT_TRUE(GetValue(report,
489                        StatsReport::kStatsValueNameAnaBitrateActionCounter,
490                        &value_in_report));
491   ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
492   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.bitrate_action_counter),
493             value_in_report);
494   EXPECT_TRUE(GetValue(report,
495                        StatsReport::kStatsValueNameAnaChannelActionCounter,
496                        &value_in_report));
497   ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
498   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.channel_action_counter),
499             value_in_report);
500   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
501                        &value_in_report));
502   ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
503   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.dtx_action_counter),
504             value_in_report);
505   EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
506                        &value_in_report));
507   ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
508   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.fec_action_counter),
509             value_in_report);
510   EXPECT_TRUE(GetValue(
511       report, StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
512       &value_in_report));
513   ASSERT_TRUE(sinfo.ana_statistics.frame_length_increase_counter);
514   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_increase_counter),
515             value_in_report);
516   EXPECT_TRUE(GetValue(
517       report, StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
518       &value_in_report));
519   ASSERT_TRUE(sinfo.ana_statistics.frame_length_decrease_counter);
520   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_decrease_counter),
521             value_in_report);
522   EXPECT_TRUE(GetValue(report,
523                        StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
524                        &value_in_report));
525   ASSERT_TRUE(sinfo.ana_statistics.uplink_packet_loss_fraction);
526   EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.uplink_packet_loss_fraction),
527             value_in_report);
528 }
529 
530 // Helper methods to avoid duplication of code.
InitVoiceSenderInfo(cricket::VoiceSenderInfo * voice_sender_info,uint32_t ssrc=kSsrcOfTrack)531 void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info,
532                          uint32_t ssrc = kSsrcOfTrack) {
533   voice_sender_info->add_ssrc(ssrc);
534   voice_sender_info->codec_name = "fake_codec";
535   voice_sender_info->payload_bytes_sent = 88;
536   voice_sender_info->header_and_padding_bytes_sent = 12;
537   voice_sender_info->packets_sent = 101;
538   voice_sender_info->rtt_ms = 102;
539   voice_sender_info->fraction_lost = 103;
540   voice_sender_info->jitter_ms = 104;
541   voice_sender_info->packets_lost = 105;
542   voice_sender_info->audio_level = 107;
543   voice_sender_info->apm_statistics.echo_return_loss = 108;
544   voice_sender_info->apm_statistics.echo_return_loss_enhancement = 109;
545   voice_sender_info->apm_statistics.delay_median_ms = 110;
546   voice_sender_info->apm_statistics.delay_standard_deviation_ms = 111;
547   voice_sender_info->ana_statistics.bitrate_action_counter = 112;
548   voice_sender_info->ana_statistics.channel_action_counter = 113;
549   voice_sender_info->ana_statistics.dtx_action_counter = 114;
550   voice_sender_info->ana_statistics.fec_action_counter = 115;
551   voice_sender_info->ana_statistics.frame_length_increase_counter = 116;
552   voice_sender_info->ana_statistics.frame_length_decrease_counter = 117;
553   voice_sender_info->ana_statistics.uplink_packet_loss_fraction = 118.0;
554 }
555 
UpdateVoiceSenderInfoFromAudioTrack(AudioTrackInterface * audio_track,cricket::VoiceSenderInfo * voice_sender_info,bool has_remote_tracks)556 void UpdateVoiceSenderInfoFromAudioTrack(
557     AudioTrackInterface* audio_track,
558     cricket::VoiceSenderInfo* voice_sender_info,
559     bool has_remote_tracks) {
560   audio_track->GetSignalLevel(&voice_sender_info->audio_level);
561   AudioProcessorInterface::AudioProcessorStatistics audio_processor_stats =
562       audio_track->GetAudioProcessor()->GetStats(has_remote_tracks);
563   voice_sender_info->apm_statistics = audio_processor_stats.apm_statistics;
564 }
565 
InitVoiceReceiverInfo(cricket::VoiceReceiverInfo * voice_receiver_info)566 void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) {
567   voice_receiver_info->add_ssrc(kSsrcOfTrack);
568   voice_receiver_info->payload_bytes_rcvd = 98;
569   voice_receiver_info->header_and_padding_bytes_rcvd = 12;
570   voice_receiver_info->packets_rcvd = 111;
571   voice_receiver_info->packets_lost = 114;
572   voice_receiver_info->jitter_ms = 116;
573   voice_receiver_info->jitter_buffer_ms = 117;
574   voice_receiver_info->jitter_buffer_preferred_ms = 118;
575   voice_receiver_info->delay_estimate_ms = 119;
576   voice_receiver_info->audio_level = 120;
577   voice_receiver_info->expand_rate = 121;
578   voice_receiver_info->speech_expand_rate = 122;
579   voice_receiver_info->secondary_decoded_rate = 123;
580   voice_receiver_info->accelerate_rate = 124;
581   voice_receiver_info->preemptive_expand_rate = 125;
582   voice_receiver_info->secondary_discarded_rate = 126;
583   voice_receiver_info->decoding_codec_plc = 127;
584 }
585 
586 class LegacyStatsCollectorForTest : public LegacyStatsCollector {
587  public:
LegacyStatsCollectorForTest(PeerConnectionInternal * pc)588   explicit LegacyStatsCollectorForTest(PeerConnectionInternal* pc)
589       : LegacyStatsCollector(pc), time_now_(19477) {}
590 
GetTimeNow()591   double GetTimeNow() override { return time_now_; }
592 
593  private:
594   double time_now_;
595 };
596 
597 class LegacyStatsCollectorTest : public ::testing::Test {
598  protected:
CreatePeerConnection()599   rtc::scoped_refptr<FakePeerConnectionForStats> CreatePeerConnection() {
600     return rtc::make_ref_counted<FakePeerConnectionForStats>();
601   }
602 
CreateStatsCollector(PeerConnectionInternal * pc)603   std::unique_ptr<LegacyStatsCollectorForTest> CreateStatsCollector(
604       PeerConnectionInternal* pc) {
605     return std::make_unique<LegacyStatsCollectorForTest>(pc);
606   }
607 
VerifyAudioTrackStats(FakeAudioTrack * audio_track,LegacyStatsCollectorForTest * stats,const VoiceMediaInfo & voice_info,StatsReports * reports)608   void VerifyAudioTrackStats(FakeAudioTrack* audio_track,
609                              LegacyStatsCollectorForTest* stats,
610                              const VoiceMediaInfo& voice_info,
611                              StatsReports* reports) {
612     stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
613     stats->InvalidateCache();
614     stats->GetStats(nullptr, reports);
615 
616     // Verify the existence of the track report.
617     const StatsReport* report =
618         FindNthReportByType(*reports, StatsReport::kStatsReportTypeSsrc, 1);
619     ASSERT_TRUE(report);
620     EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
621     std::string track_id =
622         ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameTrackId);
623     EXPECT_EQ(audio_track->id(), track_id);
624     std::string ssrc_id =
625         ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameSsrc);
626     EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
627 
628     std::string media_type =
629         ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameMediaType);
630     EXPECT_EQ("audio", media_type);
631 
632     // Verifies the values in the track report.
633     if (!voice_info.senders.empty()) {
634       VerifyVoiceSenderInfoReport(report, voice_info.senders[0]);
635     }
636     if (!voice_info.receivers.empty()) {
637       VerifyVoiceReceiverInfoReport(report, voice_info.receivers[0]);
638     }
639 
640     // Verify we get the same result by passing a track to GetStats().
641     StatsReports track_reports;  // returned values.
642     stats->GetStats(audio_track, &track_reports);
643     const StatsReport* track_report = FindNthReportByType(
644         track_reports, StatsReport::kStatsReportTypeSsrc, 1);
645     ASSERT_TRUE(track_report);
646     EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
647     track_id = ExtractSsrcStatsValue(track_reports,
648                                      StatsReport::kStatsValueNameTrackId);
649     EXPECT_EQ(audio_track->id(), track_id);
650     ssrc_id =
651         ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameSsrc);
652     EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
653     if (!voice_info.senders.empty()) {
654       VerifyVoiceSenderInfoReport(track_report, voice_info.senders[0]);
655     }
656     if (!voice_info.receivers.empty()) {
657       VerifyVoiceReceiverInfoReport(track_report, voice_info.receivers[0]);
658     }
659   }
660 
TestCertificateReports(const rtc::FakeSSLIdentity & local_identity,const std::vector<std::string> & local_ders,const rtc::FakeSSLIdentity & remote_identity,const std::vector<std::string> & remote_ders)661   void TestCertificateReports(const rtc::FakeSSLIdentity& local_identity,
662                               const std::vector<std::string>& local_ders,
663                               const rtc::FakeSSLIdentity& remote_identity,
664                               const std::vector<std::string>& remote_ders) {
665     const std::string kTransportName = "transport";
666 
667     auto pc = CreatePeerConnection();
668     auto stats = CreateStatsCollector(pc.get());
669 
670     pc->AddVoiceChannel("audio", kTransportName);
671 
672     // Fake stats to process.
673     TransportChannelStats channel_stats;
674     channel_stats.component = 1;
675     channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80;
676     channel_stats.ssl_cipher_suite =
677         internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
678     pc->SetTransportStats(kTransportName, channel_stats);
679 
680     // Fake certificate to report.
681     rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
682         rtc::RTCCertificate::Create(local_identity.Clone()));
683     pc->SetLocalCertificate(kTransportName, local_certificate);
684     pc->SetRemoteCertChain(kTransportName,
685                            remote_identity.cert_chain().Clone());
686 
687     stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
688 
689     StatsReports reports;
690     stats->GetStats(nullptr, &reports);
691 
692     const StatsReport* channel_report =
693         FindNthReportByType(reports, StatsReport::kStatsReportTypeComponent, 1);
694     EXPECT_TRUE(channel_report);
695 
696     // Check local certificate chain.
697     std::string local_certificate_id =
698         ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
699                           StatsReport::kStatsValueNameLocalCertificateId);
700     if (local_ders.size() > 0) {
701       EXPECT_NE(kNotFound, local_certificate_id);
702       StatsReport::Id id(IdFromCertIdString(local_certificate_id));
703       CheckCertChainReports(reports, local_ders, id);
704     } else {
705       EXPECT_EQ(kNotFound, local_certificate_id);
706     }
707 
708     // Check remote certificate chain.
709     std::string remote_certificate_id =
710         ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
711                           StatsReport::kStatsValueNameRemoteCertificateId);
712     if (remote_ders.size() > 0) {
713       EXPECT_NE(kNotFound, remote_certificate_id);
714       StatsReport::Id id(IdFromCertIdString(remote_certificate_id));
715       CheckCertChainReports(reports, remote_ders, id);
716     } else {
717       EXPECT_EQ(kNotFound, remote_certificate_id);
718     }
719 
720     // Check negotiated ciphers.
721     std::string dtls_cipher_suite =
722         ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
723                           StatsReport::kStatsValueNameDtlsCipher);
724     EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName(
725                   internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
726               dtls_cipher_suite);
727     std::string srtp_crypto_suite =
728         ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
729                           StatsReport::kStatsValueNameSrtpCipher);
730     EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::kSrtpAes128CmSha1_80),
731               srtp_crypto_suite);
732   }
733 
734  private:
735   rtc::AutoThread main_thread_;
736 };
737 
CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc)738 static rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
739     rtc::scoped_refptr<MediaStreamTrackInterface> track,
740     uint32_t ssrc) {
741   auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
742   EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
743   EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
744   EXPECT_CALL(*sender, media_type())
745       .WillRepeatedly(
746           Return(track->kind() == MediaStreamTrackInterface::kAudioKind
747                      ? cricket::MEDIA_TYPE_AUDIO
748                      : cricket::MEDIA_TYPE_VIDEO));
749   EXPECT_CALL(*sender, SetMediaChannel(_)).Times(AtMost(2));
750   EXPECT_CALL(*sender, SetTransceiverAsStopped()).Times(AtMost(1));
751   EXPECT_CALL(*sender, Stop());
752   return sender;
753 }
754 
CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc)755 static rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
756     rtc::scoped_refptr<MediaStreamTrackInterface> track,
757     uint32_t ssrc) {
758   auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
759   EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
760   EXPECT_CALL(*receiver, ssrc()).WillRepeatedly(Return(ssrc));
761   EXPECT_CALL(*receiver, media_type())
762       .WillRepeatedly(
763           Return(track->kind() == MediaStreamTrackInterface::kAudioKind
764                      ? cricket::MEDIA_TYPE_AUDIO
765                      : cricket::MEDIA_TYPE_VIDEO));
766   EXPECT_CALL(*receiver, SetMediaChannel(_)).WillRepeatedly(Return());
767   EXPECT_CALL(*receiver, Stop()).WillRepeatedly(Return());
768   return receiver;
769 }
770 
771 class StatsCollectorTrackTest : public LegacyStatsCollectorTest,
772                                 public ::testing::WithParamInterface<bool> {
773  public:
774   // Adds a outgoing video track with a given SSRC into the stats.
775   // If GetParam() returns true, the track is also inserted into the local
776   // stream, which is created if necessary.
AddOutgoingVideoTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)777   void AddOutgoingVideoTrack(FakePeerConnectionForStats* pc,
778                              LegacyStatsCollectorForTest* stats) {
779     video_track_ = VideoTrack::Create(
780         kLocalTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
781     if (GetParam()) {
782       if (!stream_)
783         stream_ = MediaStream::Create("streamid");
784       stream_->AddTrack(video_track());
785       stats->AddStream(stream_.get());
786     } else {
787       stats->AddTrack(video_track_.get());
788     }
789     pc->AddSender(CreateMockSender(video_track_, kSsrcOfTrack));
790   }
791 
792   // Adds a incoming video track with a given SSRC into the stats.
AddIncomingVideoTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)793   void AddIncomingVideoTrack(FakePeerConnectionForStats* pc,
794                              LegacyStatsCollectorForTest* stats) {
795     video_track_ = VideoTrack::Create(
796         kRemoteTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
797     if (GetParam()) {
798       stream_ = MediaStream::Create("streamid");
799       stream_->AddTrack(video_track());
800       stats->AddStream(stream_.get());
801     } else {
802       stats->AddTrack(video_track_.get());
803     }
804     pc->AddReceiver(CreateMockReceiver(video_track_, kSsrcOfTrack));
805   }
806 
807   // Adds a outgoing audio track with a given SSRC into the stats,
808   // and register it into the stats object.
809   // If GetParam() returns true, the track is also inserted into the local
810   // stream, which is created if necessary.
AddOutgoingAudioTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)811   rtc::scoped_refptr<RtpSenderInterface> AddOutgoingAudioTrack(
812       FakePeerConnectionForStats* pc,
813       LegacyStatsCollectorForTest* stats) {
814     audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kLocalTrackId);
815     if (GetParam()) {
816       if (!stream_)
817         stream_ = MediaStream::Create("streamid");
818       stream_->AddTrack(audio_track());
819       stats->AddStream(stream_.get());
820     } else {
821       stats->AddTrack(audio_track_.get());
822     }
823     return pc->AddSender(CreateMockSender(audio_track_, kSsrcOfTrack));
824   }
825 
826   // Adds a incoming audio track with a given SSRC into the stats.
AddIncomingAudioTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)827   void AddIncomingAudioTrack(FakePeerConnectionForStats* pc,
828                              LegacyStatsCollectorForTest* stats) {
829     audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
830     if (GetParam()) {
831       if (stream_ == nullptr)
832         stream_ = MediaStream::Create("streamid");
833       stream_->AddTrack(audio_track());
834       stats->AddStream(stream_.get());
835     } else {
836       stats->AddTrack(audio_track_.get());
837     }
838     pc->AddReceiver(CreateMockReceiver(audio_track_, kSsrcOfTrack));
839   }
840 
audio_track()841   rtc::scoped_refptr<AudioTrackInterface> audio_track() { return audio_track_; }
video_track()842   rtc::scoped_refptr<VideoTrackInterface> video_track() { return video_track_; }
843 
844   rtc::scoped_refptr<MediaStream> stream_;
845   rtc::scoped_refptr<VideoTrack> video_track_;
846   rtc::scoped_refptr<FakeAudioTrack> audio_track_;
847 };
848 
TEST_F(LegacyStatsCollectorTest,FilterOutNegativeDataChannelId)849 TEST_F(LegacyStatsCollectorTest, FilterOutNegativeDataChannelId) {
850   auto pc = CreatePeerConnection();
851   auto stats = CreateStatsCollector(pc.get());
852 
853   pc->AddSctpDataChannel("hacks");
854 
855   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
856   StatsReports reports;
857   stats->GetStats(nullptr, &reports);
858 
859   const StatsReport* report =
860       FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
861 
862   std::string value_in_report;
863   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameDataChannelId,
864                         &value_in_report));
865 }
866 
867 // Verify that ExtractDataInfo populates reports.
TEST_F(LegacyStatsCollectorTest,ExtractDataInfo)868 TEST_F(LegacyStatsCollectorTest, ExtractDataInfo) {
869   const std::string kDataChannelLabel = "hacks";
870   constexpr int kDataChannelId = 31337;
871   const std::string kConnectingString = DataChannelInterface::DataStateString(
872       DataChannelInterface::DataState::kConnecting);
873 
874   auto pc = CreatePeerConnection();
875   auto stats = CreateStatsCollector(pc.get());
876 
877   InternalDataChannelInit init;
878   init.id = kDataChannelId;
879   pc->AddSctpDataChannel(kDataChannelLabel, init);
880 
881   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
882   StatsReports reports;
883   stats->GetStats(nullptr, &reports);
884 
885   const StatsReport* report =
886       FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
887 
888   StatsReport::Id report_id = StatsReport::NewTypedIntId(
889       StatsReport::kStatsReportTypeDataChannel, kDataChannelId);
890 
891   EXPECT_TRUE(report_id->Equals(report->id()));
892 
893   EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
894   EXPECT_EQ(kDataChannelLabel,
895             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
896                               StatsReport::kStatsValueNameLabel));
897   EXPECT_EQ(rtc::ToString(kDataChannelId),
898             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
899                               StatsReport::kStatsValueNameDataChannelId));
900   EXPECT_EQ(kConnectingString,
901             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
902                               StatsReport::kStatsValueNameState));
903   EXPECT_EQ("",
904             ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
905                               StatsReport::kStatsValueNameProtocol));
906 }
907 
908 // This test verifies that 64-bit counters are passed successfully.
TEST_P(StatsCollectorTrackTest,BytesCounterHandles64Bits)909 TEST_P(StatsCollectorTrackTest, BytesCounterHandles64Bits) {
910   // The number of bytes must be larger than 0xFFFFFFFF for this test.
911   constexpr int64_t kBytesSent = 12345678901234LL;
912 
913   auto pc = CreatePeerConnection();
914   auto stats = CreateStatsCollector(pc.get());
915 
916   VideoSenderInfo video_sender_info;
917   video_sender_info.add_ssrc(1234);
918   video_sender_info.payload_bytes_sent = kBytesSent;
919   video_sender_info.header_and_padding_bytes_sent = 0;
920   VideoMediaInfo video_info;
921   video_info.aggregated_senders.push_back(video_sender_info);
922 
923   pc->AddVideoChannel("video", "transport", video_info);
924 
925   AddOutgoingVideoTrack(pc.get(), stats.get());
926 
927   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
928   StatsReports reports;
929   stats->GetStats(nullptr, &reports);
930 
931   EXPECT_EQ(
932       rtc::ToString(kBytesSent),
933       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
934 }
935 
936 // Test that audio BWE information is reported via stats.
TEST_P(StatsCollectorTrackTest,AudioBandwidthEstimationInfoIsReported)937 TEST_P(StatsCollectorTrackTest, AudioBandwidthEstimationInfoIsReported) {
938   // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
939   // BWE.
940   constexpr int64_t kBytesSent = 12345678901234LL;
941   constexpr int kSendBandwidth = 1234567;
942   constexpr int kRecvBandwidth = 12345678;
943   constexpr int kPacerDelay = 123;
944 
945   auto pc = CreatePeerConnection();
946   auto stats = CreateStatsCollector(pc.get());
947 
948   VoiceSenderInfo voice_sender_info;
949   voice_sender_info.add_ssrc(1234);
950   voice_sender_info.payload_bytes_sent = kBytesSent - 12;
951   voice_sender_info.header_and_padding_bytes_sent = 12;
952   VoiceMediaInfo voice_info;
953   voice_info.senders.push_back(voice_sender_info);
954 
955   auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
956   voice_media_channel->SetStats(voice_info);
957 
958   AddOutgoingAudioTrack(pc.get(), stats.get());
959 
960   Call::Stats call_stats;
961   call_stats.send_bandwidth_bps = kSendBandwidth;
962   call_stats.recv_bandwidth_bps = kRecvBandwidth;
963   call_stats.pacer_delay_ms = kPacerDelay;
964   pc->SetCallStats(call_stats);
965 
966   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
967   StatsReports reports;
968   stats->GetStats(nullptr, &reports);
969 
970   EXPECT_EQ(
971       rtc::ToString(kBytesSent),
972       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
973   EXPECT_EQ(rtc::ToString(kSendBandwidth),
974             ExtractBweStatsValue(
975                 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
976   EXPECT_EQ(
977       rtc::ToString(kRecvBandwidth),
978       ExtractBweStatsValue(
979           reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
980   EXPECT_EQ(
981       rtc::ToString(kPacerDelay),
982       ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
983 }
984 
985 // Test that video BWE information is reported via stats.
TEST_P(StatsCollectorTrackTest,VideoBandwidthEstimationInfoIsReported)986 TEST_P(StatsCollectorTrackTest, VideoBandwidthEstimationInfoIsReported) {
987   // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
988   // BWE.
989   constexpr int64_t kBytesSent = 12345678901234LL;
990   constexpr int kSendBandwidth = 1234567;
991   constexpr int kRecvBandwidth = 12345678;
992   constexpr int kPacerDelay = 123;
993 
994   auto pc = CreatePeerConnection();
995   auto stats = CreateStatsCollector(pc.get());
996 
997   VideoSenderInfo video_sender_info;
998   video_sender_info.add_ssrc(1234);
999   video_sender_info.payload_bytes_sent = kBytesSent - 12;
1000   video_sender_info.header_and_padding_bytes_sent = 12;
1001 
1002   VideoMediaInfo video_info;
1003   video_info.aggregated_senders.push_back(video_sender_info);
1004 
1005   pc->AddVideoChannel("video", "transport", video_info);
1006 
1007   AddOutgoingVideoTrack(pc.get(), stats.get());
1008 
1009   Call::Stats call_stats;
1010   call_stats.send_bandwidth_bps = kSendBandwidth;
1011   call_stats.recv_bandwidth_bps = kRecvBandwidth;
1012   call_stats.pacer_delay_ms = kPacerDelay;
1013   pc->SetCallStats(call_stats);
1014 
1015   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1016   StatsReports reports;
1017   stats->GetStats(nullptr, &reports);
1018 
1019   EXPECT_EQ(
1020       rtc::ToString(kBytesSent),
1021       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
1022   EXPECT_EQ(rtc::ToString(kSendBandwidth),
1023             ExtractBweStatsValue(
1024                 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
1025   EXPECT_EQ(
1026       rtc::ToString(kRecvBandwidth),
1027       ExtractBweStatsValue(
1028           reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
1029   EXPECT_EQ(
1030       rtc::ToString(kPacerDelay),
1031       ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
1032 }
1033 
1034 // This test verifies that an object of type "googSession" always
1035 // exists in the returned stats.
TEST_F(LegacyStatsCollectorTest,SessionObjectExists)1036 TEST_F(LegacyStatsCollectorTest, SessionObjectExists) {
1037   auto pc = CreatePeerConnection();
1038   auto stats = CreateStatsCollector(pc.get());
1039 
1040   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1041   StatsReports reports;
1042   stats->GetStats(nullptr, &reports);
1043 
1044   EXPECT_TRUE(
1045       FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
1046 }
1047 
1048 // This test verifies that only one object of type "googSession" exists
1049 // in the returned stats.
TEST_F(LegacyStatsCollectorTest,OnlyOneSessionObjectExists)1050 TEST_F(LegacyStatsCollectorTest, OnlyOneSessionObjectExists) {
1051   auto pc = CreatePeerConnection();
1052   auto stats = CreateStatsCollector(pc.get());
1053 
1054   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1055   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1056   StatsReports reports;
1057   stats->GetStats(nullptr, &reports);
1058 
1059   EXPECT_TRUE(
1060       FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
1061   EXPECT_FALSE(
1062       FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 2));
1063 }
1064 
1065 // This test verifies that the empty track report exists in the returned stats
1066 // without calling StatsCollector::UpdateStats.
TEST_P(StatsCollectorTrackTest,TrackObjectExistsWithoutUpdateStats)1067 TEST_P(StatsCollectorTrackTest, TrackObjectExistsWithoutUpdateStats) {
1068   auto pc = CreatePeerConnection();
1069   auto stats = CreateStatsCollector(pc.get());
1070 
1071   pc->AddVideoChannel("video", "transport");
1072   AddOutgoingVideoTrack(pc.get(), stats.get());
1073 
1074   // Verfies the existence of the track report.
1075   StatsReports reports;
1076   stats->GetStats(nullptr, &reports);
1077   ASSERT_EQ(1u, reports.size());
1078   EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type());
1079   EXPECT_EQ(0, reports[0]->timestamp());
1080 
1081   std::string trackValue =
1082       ExtractStatsValue(StatsReport::kStatsReportTypeTrack, reports,
1083                         StatsReport::kStatsValueNameTrackId);
1084   EXPECT_EQ(kLocalTrackId, trackValue);
1085 }
1086 
1087 // This test verifies that the empty track report exists in the returned stats
1088 // when StatsCollector::UpdateStats is called with ssrc stats.
TEST_P(StatsCollectorTrackTest,TrackAndSsrcObjectExistAfterUpdateSsrcStats)1089 TEST_P(StatsCollectorTrackTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
1090   constexpr int64_t kBytesSent = 12345678901234LL;
1091 
1092   auto pc = CreatePeerConnection();
1093   auto stats = CreateStatsCollector(pc.get());
1094 
1095   VideoSenderInfo video_sender_info;
1096   video_sender_info.add_ssrc(1234);
1097   video_sender_info.payload_bytes_sent = kBytesSent - 12;
1098   video_sender_info.header_and_padding_bytes_sent = 12;
1099   VideoMediaInfo video_info;
1100   video_info.aggregated_senders.push_back(video_sender_info);
1101 
1102   pc->AddVideoChannel("video", "transport", video_info);
1103 
1104   AddOutgoingVideoTrack(pc.get(), stats.get());
1105 
1106   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1107   StatsReports reports;
1108   stats->GetStats(nullptr, &reports);
1109 
1110   // `reports` should contain at least one session report, one track report,
1111   // and one ssrc report.
1112   EXPECT_LE(3u, reports.size());
1113   const StatsReport* track_report =
1114       FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1115   EXPECT_TRUE(track_report);
1116 
1117   // Get report for the specific `track`.
1118   reports.clear();
1119   stats->GetStats(video_track_.get(), &reports);
1120   // `reports` should contain at least one session report, one track report,
1121   // and one ssrc report.
1122   EXPECT_LE(3u, reports.size());
1123   track_report =
1124       FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1125   ASSERT_TRUE(track_report);
1126   EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1127 
1128   std::string ssrc_id =
1129       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1130   EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1131 
1132   std::string track_id =
1133       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1134   EXPECT_EQ(kLocalTrackId, track_id);
1135 
1136   std::string media_type =
1137       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameMediaType);
1138   EXPECT_EQ("video", media_type);
1139 }
1140 
1141 // This test verifies that an SSRC object has the identifier of a Transport
1142 // stats object, and that this transport stats object exists in stats.
TEST_P(StatsCollectorTrackTest,TransportObjectLinkedFromSsrcObject)1143 TEST_P(StatsCollectorTrackTest, TransportObjectLinkedFromSsrcObject) {
1144   constexpr int64_t kBytesSent = 12345678901234LL;
1145 
1146   auto pc = CreatePeerConnection();
1147   auto stats = CreateStatsCollector(pc.get());
1148 
1149   VideoSenderInfo video_sender_info;
1150   video_sender_info.add_ssrc(1234);
1151   video_sender_info.payload_bytes_sent = kBytesSent - 12;
1152   video_sender_info.header_and_padding_bytes_sent = 12;
1153   VideoMediaInfo video_info;
1154   video_info.aggregated_senders.push_back(video_sender_info);
1155 
1156   pc->AddVideoChannel("video", "transport", video_info);
1157 
1158   AddOutgoingVideoTrack(pc.get(), stats.get());
1159 
1160   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1161   StatsReports reports;
1162   stats->GetStats(nullptr, &reports);
1163 
1164   std::string transport_id =
1165       ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports,
1166                         StatsReport::kStatsValueNameTransportId);
1167   ASSERT_NE(kNotFound, transport_id);
1168 
1169   // Transport id component ID will always be 1.
1170   // This has assumptions about how the ID is constructed.  As is, this is
1171   // OK since this is for testing purposes only, but if we ever need this
1172   // in production, we should add a generic method that does this.
1173   size_t index = transport_id.find('-');
1174   ASSERT_NE(std::string::npos, index);
1175   std::string content = transport_id.substr(index + 1);
1176   index = content.rfind('-');
1177   ASSERT_NE(std::string::npos, index);
1178   content = content.substr(0, index);
1179   StatsReport::Id id(StatsReport::NewComponentId(content, 1));
1180   ASSERT_EQ(transport_id, id->ToString());
1181   const StatsReport* transport_report = FindReportById(reports, id);
1182   ASSERT_TRUE(transport_report);
1183 }
1184 
1185 // This test verifies that a remote stats object will not be created for
1186 // an outgoing SSRC where remote stats are not returned.
TEST_P(StatsCollectorTrackTest,RemoteSsrcInfoIsAbsent)1187 TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsAbsent) {
1188   auto pc = CreatePeerConnection();
1189   auto stats = CreateStatsCollector(pc.get());
1190 
1191   pc->AddVideoChannel("video", "transport");
1192   AddOutgoingVideoTrack(pc.get(), stats.get());
1193 
1194   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1195   StatsReports reports;
1196   stats->GetStats(nullptr, &reports);
1197 
1198   const StatsReport* remote_report =
1199       FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1200   EXPECT_FALSE(remote_report);
1201 }
1202 
1203 // This test verifies that a remote stats object will be created for
1204 // an outgoing SSRC where stats are returned.
TEST_P(StatsCollectorTrackTest,RemoteSsrcInfoIsPresent)1205 TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsPresent) {
1206   auto pc = CreatePeerConnection();
1207   auto stats = CreateStatsCollector(pc.get());
1208 
1209   SsrcReceiverInfo remote_ssrc_stats;
1210   remote_ssrc_stats.timestamp = 12345.678;
1211   remote_ssrc_stats.ssrc = kSsrcOfTrack;
1212   VideoSenderInfo video_sender_info;
1213   video_sender_info.add_ssrc(kSsrcOfTrack);
1214   video_sender_info.remote_stats.push_back(remote_ssrc_stats);
1215   VideoMediaInfo video_info;
1216   video_info.aggregated_senders.push_back(video_sender_info);
1217 
1218   pc->AddVideoChannel("video", "transport", video_info);
1219 
1220   AddOutgoingVideoTrack(pc.get(), stats.get());
1221 
1222   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1223   StatsReports reports;
1224   stats->GetStats(nullptr, &reports);
1225 
1226   const StatsReport* remote_report =
1227       FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1228   ASSERT_TRUE(remote_report);
1229   EXPECT_EQ(12345.678, remote_report->timestamp());
1230 }
1231 
1232 // This test verifies that the empty track report exists in the returned stats
1233 // when StatsCollector::UpdateStats is called with ssrc stats.
TEST_P(StatsCollectorTrackTest,ReportsFromRemoteTrack)1234 TEST_P(StatsCollectorTrackTest, ReportsFromRemoteTrack) {
1235   constexpr int64_t kNumOfPacketsConcealed = 54321;
1236 
1237   auto pc = CreatePeerConnection();
1238   auto stats = CreateStatsCollector(pc.get());
1239 
1240   VideoReceiverInfo video_receiver_info;
1241   video_receiver_info.add_ssrc(1234);
1242   video_receiver_info.packets_concealed = kNumOfPacketsConcealed;
1243   VideoMediaInfo video_info;
1244   video_info.receivers.push_back(video_receiver_info);
1245 
1246   pc->AddVideoChannel("video", "transport", video_info);
1247 
1248   AddIncomingVideoTrack(pc.get(), stats.get());
1249 
1250   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1251   StatsReports reports;
1252   stats->GetStats(nullptr, &reports);
1253 
1254   // `reports` should contain at least one session report, one track report,
1255   // and one ssrc report.
1256   EXPECT_LE(3u, reports.size());
1257   const StatsReport* track_report =
1258       FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1259   ASSERT_TRUE(track_report);
1260   EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1261 
1262   std::string ssrc_id =
1263       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1264   EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1265 
1266   std::string track_id =
1267       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1268   EXPECT_EQ(kRemoteTrackId, track_id);
1269 }
1270 
1271 // This test verifies the Ice Candidate report should contain the correct
1272 // information from local/remote candidates.
TEST_F(LegacyStatsCollectorTest,IceCandidateReport)1273 TEST_F(LegacyStatsCollectorTest, IceCandidateReport) {
1274   const std::string kTransportName = "transport";
1275   const rtc::AdapterType kNetworkType = rtc::ADAPTER_TYPE_ETHERNET;
1276   constexpr uint32_t kPriority = 1000;
1277 
1278   constexpr int kLocalPort = 2000;
1279   const std::string kLocalIp = "192.168.0.1";
1280   const rtc::SocketAddress kLocalAddress(kLocalIp, kLocalPort);
1281 
1282   constexpr int kRemotePort = 2001;
1283   const std::string kRemoteIp = "192.168.0.2";
1284   const rtc::SocketAddress kRemoteAddress(kRemoteIp, kRemotePort);
1285 
1286   auto pc = CreatePeerConnection();
1287   auto stats = CreateStatsCollector(pc.get());
1288 
1289   cricket::Candidate local;
1290   EXPECT_GT(local.id().length(), 0u);
1291   local.set_type(cricket::LOCAL_PORT_TYPE);
1292   local.set_protocol(cricket::UDP_PROTOCOL_NAME);
1293   local.set_address(kLocalAddress);
1294   local.set_priority(kPriority);
1295   local.set_network_type(kNetworkType);
1296 
1297   cricket::Candidate remote;
1298   EXPECT_GT(remote.id().length(), 0u);
1299   remote.set_type(cricket::PRFLX_PORT_TYPE);
1300   remote.set_protocol(cricket::UDP_PROTOCOL_NAME);
1301   remote.set_address(kRemoteAddress);
1302   remote.set_priority(kPriority);
1303   remote.set_network_type(kNetworkType);
1304 
1305   ConnectionInfo connection_info;
1306   connection_info.local_candidate = local;
1307   connection_info.remote_candidate = remote;
1308   TransportChannelStats channel_stats;
1309   channel_stats.ice_transport_stats.connection_infos.push_back(connection_info);
1310 
1311   pc->AddVoiceChannel("audio", kTransportName);
1312   pc->SetTransportStats(kTransportName, channel_stats);
1313 
1314   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1315   StatsReports reports;
1316   stats->GetStats(nullptr, &reports);
1317 
1318   // Verify the local candidate report is populated correctly.
1319   EXPECT_EQ(
1320       "Cand-" + local.id(),
1321       ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1322                         StatsReport::kStatsValueNameLocalCandidateId));
1323   EXPECT_EQ(
1324       kLocalIp,
1325       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1326                         StatsReport::kStatsValueNameCandidateIPAddress));
1327   EXPECT_EQ(
1328       rtc::ToString(kLocalPort),
1329       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1330                         StatsReport::kStatsValueNameCandidatePortNumber));
1331   EXPECT_EQ(
1332       cricket::UDP_PROTOCOL_NAME,
1333       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1334                         StatsReport::kStatsValueNameCandidateTransportType));
1335   EXPECT_EQ(
1336       rtc::ToString(kPriority),
1337       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1338                         StatsReport::kStatsValueNameCandidatePriority));
1339   EXPECT_EQ(
1340       IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE),
1341       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1342                         StatsReport::kStatsValueNameCandidateType));
1343   EXPECT_EQ(
1344       AdapterTypeToStatsType(kNetworkType),
1345       ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1346                         StatsReport::kStatsValueNameCandidateNetworkType));
1347 
1348   // Verify the remote candidate report is populated correctly.
1349   EXPECT_EQ(
1350       "Cand-" + remote.id(),
1351       ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1352                         StatsReport::kStatsValueNameRemoteCandidateId));
1353   EXPECT_EQ(kRemoteIp,
1354             ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1355                               reports,
1356                               StatsReport::kStatsValueNameCandidateIPAddress));
1357   EXPECT_EQ(rtc::ToString(kRemotePort),
1358             ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1359                               reports,
1360                               StatsReport::kStatsValueNameCandidatePortNumber));
1361   EXPECT_EQ(cricket::UDP_PROTOCOL_NAME,
1362             ExtractStatsValue(
1363                 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1364                 StatsReport::kStatsValueNameCandidateTransportType));
1365   EXPECT_EQ(rtc::ToString(kPriority),
1366             ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1367                               reports,
1368                               StatsReport::kStatsValueNameCandidatePriority));
1369   EXPECT_EQ(
1370       IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE),
1371       ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1372                         reports, StatsReport::kStatsValueNameCandidateType));
1373   EXPECT_EQ(kNotFound,
1374             ExtractStatsValue(
1375                 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1376                 StatsReport::kStatsValueNameCandidateNetworkType));
1377 }
1378 
1379 // This test verifies that all chained certificates are correctly
1380 // reported
TEST_F(LegacyStatsCollectorTest,ChainedCertificateReportsCreated)1381 TEST_F(LegacyStatsCollectorTest, ChainedCertificateReportsCreated) {
1382   // Build local certificate chain.
1383   std::vector<std::string> local_ders(5);
1384   local_ders[0] = "These";
1385   local_ders[1] = "are";
1386   local_ders[2] = "some";
1387   local_ders[3] = "der";
1388   local_ders[4] = "values";
1389   rtc::FakeSSLIdentity local_identity(DersToPems(local_ders));
1390 
1391   // Build remote certificate chain
1392   std::vector<std::string> remote_ders(4);
1393   remote_ders[0] = "A";
1394   remote_ders[1] = "non-";
1395   remote_ders[2] = "intersecting";
1396   remote_ders[3] = "set";
1397   rtc::FakeSSLIdentity remote_identity(DersToPems(remote_ders));
1398 
1399   TestCertificateReports(local_identity, local_ders, remote_identity,
1400                          remote_ders);
1401 }
1402 
1403 // This test verifies that all certificates without chains are correctly
1404 // reported.
TEST_F(LegacyStatsCollectorTest,ChainlessCertificateReportsCreated)1405 TEST_F(LegacyStatsCollectorTest, ChainlessCertificateReportsCreated) {
1406   // Build local certificate.
1407   std::string local_der = "This is the local der.";
1408   rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
1409 
1410   // Build remote certificate.
1411   std::string remote_der = "This is somebody else's der.";
1412   rtc::FakeSSLIdentity remote_identity(DerToPem(remote_der));
1413 
1414   TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1415                          remote_identity,
1416                          std::vector<std::string>(1, remote_der));
1417 }
1418 
1419 // This test verifies that the stats are generated correctly when no
1420 // transport is present.
TEST_F(LegacyStatsCollectorTest,NoTransport)1421 TEST_F(LegacyStatsCollectorTest, NoTransport) {
1422   auto pc = CreatePeerConnection();
1423   auto stats = CreateStatsCollector(pc.get());
1424 
1425   // This will cause the fake PeerConnection to generate a TransportStats entry
1426   // but with only a single dummy TransportChannelStats.
1427   pc->AddVoiceChannel("audio", "transport");
1428 
1429   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1430   StatsReports reports;
1431   stats->GetStats(nullptr, &reports);
1432 
1433   // Check that the local certificate is absent.
1434   std::string local_certificate_id =
1435       ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1436                         StatsReport::kStatsValueNameLocalCertificateId);
1437   ASSERT_EQ(kNotFound, local_certificate_id);
1438 
1439   // Check that the remote certificate is absent.
1440   std::string remote_certificate_id =
1441       ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1442                         StatsReport::kStatsValueNameRemoteCertificateId);
1443   ASSERT_EQ(kNotFound, remote_certificate_id);
1444 
1445   // Check that the negotiated ciphers are absent.
1446   std::string dtls_cipher_suite =
1447       ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1448                         StatsReport::kStatsValueNameDtlsCipher);
1449   ASSERT_EQ(kNotFound, dtls_cipher_suite);
1450   std::string srtp_crypto_suite =
1451       ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1452                         StatsReport::kStatsValueNameSrtpCipher);
1453   ASSERT_EQ(kNotFound, srtp_crypto_suite);
1454 }
1455 
1456 // This test verifies that a remote certificate with an unsupported digest
1457 // algorithm is correctly ignored.
TEST_F(LegacyStatsCollectorTest,UnsupportedDigestIgnored)1458 TEST_F(LegacyStatsCollectorTest, UnsupportedDigestIgnored) {
1459   // Build a local certificate.
1460   std::string local_der = "This is the local der.";
1461   rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
1462 
1463   // Build a remote certificate with an unsupported digest algorithm.
1464   std::string remote_der = "This is somebody else's der.";
1465   rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der));
1466   remote_cert.set_digest_algorithm("foobar");
1467   rtc::FakeSSLIdentity remote_identity(remote_cert);
1468 
1469   TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1470                          remote_identity, std::vector<std::string>());
1471 }
1472 
1473 // This test verifies that the audio/video related stats which are -1 initially
1474 // will be filtered out.
TEST_P(StatsCollectorTrackTest,FilterOutNegativeInitialValues)1475 TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) {
1476   // This test uses streams, but only works for the stream case.
1477   if (!GetParam()) {
1478     return;
1479   }
1480 
1481   auto pc = CreatePeerConnection();
1482   auto stats = CreateStatsCollector(pc.get());
1483 
1484   // Create a local stream with a local audio track and adds it to the stats.
1485   stream_ = MediaStream::Create("streamid");
1486   auto local_track =
1487       rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
1488   stream_->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(local_track.get()));
1489   pc->AddSender(CreateMockSender(local_track, kSsrcOfTrack));
1490   if (GetParam()) {
1491     stats->AddStream(stream_.get());
1492   }
1493   stats->AddLocalAudioTrack(local_track.get(), kSsrcOfTrack);
1494 
1495   // Create a remote stream with a remote audio track and adds it to the stats.
1496   rtc::scoped_refptr<MediaStream> remote_stream(
1497       MediaStream::Create("remotestreamid"));
1498   rtc::scoped_refptr<AudioTrackInterface> remote_track =
1499       rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kRemoteTrackId);
1500   remote_stream->AddTrack(remote_track);
1501   pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
1502   if (GetParam()) {
1503     stats->AddStream(remote_stream.get());
1504   }
1505 
1506   VoiceSenderInfo voice_sender_info;
1507   voice_sender_info.add_ssrc(kSsrcOfTrack);
1508   // These values are set to -1 initially in audio_send_stream.
1509   // The voice_sender_info will read the values from audio_send_stream.
1510   voice_sender_info.rtt_ms = -1;
1511   voice_sender_info.packets_lost = -1;
1512   voice_sender_info.jitter_ms = -1;
1513 
1514   // Some of the contents in `voice_sender_info` needs to be updated from the
1515   // `audio_track_`.
1516   UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &voice_sender_info,
1517                                       true);
1518 
1519   VoiceReceiverInfo voice_receiver_info;
1520   voice_receiver_info.add_ssrc(kSsrcOfTrack);
1521   voice_receiver_info.capture_start_ntp_time_ms = -1;
1522   voice_receiver_info.audio_level = -1;
1523 
1524   // Constructs an ssrc stats update.
1525   VoiceMediaInfo voice_info;
1526   voice_info.senders.push_back(voice_sender_info);
1527   voice_info.receivers.push_back(voice_receiver_info);
1528 
1529   auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1530   voice_media_channel->SetStats(voice_info);
1531 
1532   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1533 
1534   // Get stats for the local track.
1535   StatsReports reports;
1536   stats->GetStats(local_track.get(), &reports);
1537   const StatsReport* report =
1538       FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1539   ASSERT_TRUE(report);
1540   // The -1 will not be added to the stats report.
1541   std::string value_in_report;
1542   EXPECT_FALSE(
1543       GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
1544   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
1545                         &value_in_report));
1546   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
1547                         &value_in_report));
1548   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
1549                         &value_in_report));
1550   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
1551                         &value_in_report));
1552 
1553   // Get stats for the remote track.
1554   reports.clear();
1555   stats->GetStats(remote_track.get(), &reports);
1556   report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1557   ASSERT_TRUE(report);
1558   EXPECT_FALSE(GetValue(report,
1559                         StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
1560                         &value_in_report));
1561   EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
1562                         &value_in_report));
1563 }
1564 
1565 // This test verifies that a local stats object can get statistics via
1566 // AudioTrackInterface::GetStats() method.
TEST_P(StatsCollectorTrackTest,GetStatsFromLocalAudioTrack)1567 TEST_P(StatsCollectorTrackTest, GetStatsFromLocalAudioTrack) {
1568   auto pc = CreatePeerConnection();
1569   auto stats = CreateStatsCollector(pc.get());
1570 
1571   AddOutgoingAudioTrack(pc.get(), stats.get());
1572   stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1573 
1574   VoiceSenderInfo voice_sender_info;
1575   InitVoiceSenderInfo(&voice_sender_info);
1576   UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1577                                       false);
1578   VoiceMediaInfo voice_info;
1579   voice_info.senders.push_back(voice_sender_info);
1580 
1581   auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1582   voice_media_channel->SetStats(voice_info);
1583 
1584   StatsReports reports;  // returned values.
1585   VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1586 
1587   // Verify that there is no remote report for the local audio track because
1588   // we did not set it up.
1589   const StatsReport* remote_report =
1590       FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1591   EXPECT_TRUE(remote_report == NULL);
1592 }
1593 
1594 // This test verifies that audio receive streams populate stats reports
1595 // correctly.
TEST_P(StatsCollectorTrackTest,GetStatsFromRemoteStream)1596 TEST_P(StatsCollectorTrackTest, GetStatsFromRemoteStream) {
1597   auto pc = CreatePeerConnection();
1598   auto stats = CreateStatsCollector(pc.get());
1599 
1600   AddIncomingAudioTrack(pc.get(), stats.get());
1601 
1602   VoiceReceiverInfo voice_receiver_info;
1603   InitVoiceReceiverInfo(&voice_receiver_info);
1604   voice_receiver_info.codec_name = "fake_codec";
1605   VoiceMediaInfo voice_info;
1606   voice_info.receivers.push_back(voice_receiver_info);
1607 
1608   auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1609   voice_media_channel->SetStats(voice_info);
1610 
1611   StatsReports reports;  // returned values.
1612   VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1613 }
1614 
1615 // This test verifies that a local stats object won't update its statistics
1616 // after a RemoveLocalAudioTrack() call.
TEST_P(StatsCollectorTrackTest,GetStatsAfterRemoveAudioStream)1617 TEST_P(StatsCollectorTrackTest, GetStatsAfterRemoveAudioStream) {
1618   auto pc = CreatePeerConnection();
1619   auto stats = CreateStatsCollector(pc.get());
1620 
1621   AddOutgoingAudioTrack(pc.get(), stats.get());
1622   stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1623 
1624   VoiceSenderInfo voice_sender_info;
1625   InitVoiceSenderInfo(&voice_sender_info);
1626   VoiceMediaInfo voice_info;
1627   voice_info.senders.push_back(voice_sender_info);
1628 
1629   auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1630   voice_media_channel->SetStats(voice_info);
1631 
1632   stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1633 
1634   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1635   StatsReports reports;
1636   stats->GetStats(nullptr, &reports);
1637 
1638   // The report will exist since we don't remove them in RemoveStream().
1639   const StatsReport* report =
1640       FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1641   ASSERT_TRUE(report);
1642   EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
1643   std::string track_id =
1644       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1645   EXPECT_EQ(kLocalTrackId, track_id);
1646   std::string ssrc_id =
1647       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1648   EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1649 
1650   // Verifies the values in the track report, no value will be changed by the
1651   // AudioTrackInterface::GetSignalValue() and
1652   // AudioProcessorInterface::GetStats();
1653   VerifyVoiceSenderInfoReport(report, voice_sender_info);
1654 }
1655 
1656 // This test verifies that when ongoing and incoming audio tracks are using
1657 // the same ssrc, they populate stats reports correctly.
TEST_P(StatsCollectorTrackTest,LocalAndRemoteTracksWithSameSsrc)1658 TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) {
1659   auto pc = CreatePeerConnection();
1660   auto stats = CreateStatsCollector(pc.get());
1661 
1662   // Create a local stream with a local audio track and adds it to the stats.
1663   AddOutgoingAudioTrack(pc.get(), stats.get());
1664   stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1665 
1666   // Create a remote stream with a remote audio track and adds it to the stats.
1667   rtc::scoped_refptr<MediaStream> remote_stream(
1668       MediaStream::Create("remotestreamid"));
1669   rtc::scoped_refptr<AudioTrackInterface> remote_track =
1670       rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
1671   pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
1672   remote_stream->AddTrack(remote_track);
1673   stats->AddStream(remote_stream.get());
1674 
1675   VoiceSenderInfo voice_sender_info;
1676   InitVoiceSenderInfo(&voice_sender_info);
1677   // Some of the contents in `voice_sender_info` needs to be updated from the
1678   // `audio_track_`.
1679   UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1680                                       true);
1681 
1682   VoiceReceiverInfo voice_receiver_info;
1683   InitVoiceReceiverInfo(&voice_receiver_info);
1684 
1685   // Constructs an ssrc stats update.
1686   VoiceMediaInfo voice_info;
1687   voice_info.senders.push_back(voice_sender_info);
1688   voice_info.receivers.push_back(voice_receiver_info);
1689 
1690   // Instruct the session to return stats containing the transport channel.
1691   auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1692   voice_media_channel->SetStats(voice_info);
1693 
1694   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1695 
1696   // Get stats for the local track.
1697   StatsReports reports;  // returned values.
1698   stats->GetStats(audio_track_.get(), &reports);
1699 
1700   const StatsReport* track_report =
1701       FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1702   ASSERT_TRUE(track_report);
1703   EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1704   std::string track_id =
1705       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1706   EXPECT_EQ(kLocalTrackId, track_id);
1707   VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
1708 
1709   // Get stats for the remote track.
1710   reports.clear();
1711   stats->GetStats(remote_track.get(), &reports);
1712   track_report =
1713       FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1714   ASSERT_TRUE(track_report);
1715   EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1716   track_id =
1717       ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1718   EXPECT_EQ(kRemoteTrackId, track_id);
1719   VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info);
1720 }
1721 
1722 // This test verifies that when two outgoing audio tracks are using the same
1723 // ssrc at different times, they populate stats reports correctly.
1724 // TODO(xians): Figure out if it is possible to encapsulate the setup and
1725 // avoid duplication of code in test cases.
TEST_P(StatsCollectorTrackTest,TwoLocalTracksWithSameSsrc)1726 TEST_P(StatsCollectorTrackTest, TwoLocalTracksWithSameSsrc) {
1727   // This test only makes sense when we're using streams.
1728   if (!GetParam()) {
1729     return;
1730   }
1731 
1732   auto pc = CreatePeerConnection();
1733   auto stats = CreateStatsCollector(pc.get());
1734 
1735   // Create a local stream with a local audio track and adds it to the stats.
1736   auto sender = AddOutgoingAudioTrack(pc.get(), stats.get());
1737   stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1738 
1739   VoiceSenderInfo voice_sender_info;
1740   InitVoiceSenderInfo(&voice_sender_info);
1741   UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1742                                       false);
1743   voice_sender_info.add_ssrc(kSsrcOfTrack);
1744   VoiceMediaInfo voice_info;
1745   voice_info.senders.push_back(voice_sender_info);
1746 
1747   auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1748   voice_media_channel->SetStats(voice_info);
1749 
1750   StatsReports reports;  // returned values.
1751   VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1752 
1753   // Remove the previous audio track from the stream.
1754   stream_->RemoveTrack(audio_track());
1755   stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1756   pc->RemoveSender(sender);
1757 
1758   // Create a new audio track and adds it to the stream and stats.
1759   static const std::string kNewTrackId = "new_track_id";
1760   auto new_audio_track = rtc::make_ref_counted<FakeAudioTrack>(kNewTrackId);
1761   pc->AddSender(CreateMockSender(new_audio_track, kSsrcOfTrack));
1762   stream_->AddTrack(
1763       rtc::scoped_refptr<AudioTrackInterface>(new_audio_track.get()));
1764 
1765   stats->AddLocalAudioTrack(new_audio_track.get(), kSsrcOfTrack);
1766   stats->InvalidateCache();
1767 
1768   VoiceSenderInfo new_voice_sender_info;
1769   InitVoiceSenderInfo(&new_voice_sender_info);
1770   UpdateVoiceSenderInfoFromAudioTrack(new_audio_track.get(),
1771                                       &new_voice_sender_info, false);
1772   VoiceMediaInfo new_voice_info;
1773   new_voice_info.senders.push_back(new_voice_sender_info);
1774   voice_media_channel->SetStats(new_voice_info);
1775 
1776   reports.clear();
1777   VerifyAudioTrackStats(new_audio_track.get(), stats.get(), new_voice_info,
1778                         &reports);
1779 }
1780 
1781 // Test that if there are two local senders with the same track then two SSRC
1782 // reports will be created, one for each sender, with the same track ID and one
1783 // track report will be created for the shared track.
TEST_P(StatsCollectorTrackTest,TwoLocalSendersWithSameTrack)1784 TEST_P(StatsCollectorTrackTest, TwoLocalSendersWithSameTrack) {
1785   constexpr uint32_t kFirstSsrc = 22;
1786   constexpr uint32_t kSecondSsrc = 33;
1787 
1788   auto pc = CreatePeerConnection();
1789   auto stats = CreateStatsCollector(pc.get());
1790 
1791   auto local_track =
1792       rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
1793   pc->AddSender(CreateMockSender(local_track, kFirstSsrc));
1794   stats->AddLocalAudioTrack(local_track.get(), kFirstSsrc);
1795   pc->AddSender(CreateMockSender(local_track, kSecondSsrc));
1796   stats->AddLocalAudioTrack(local_track.get(), kSecondSsrc);
1797 
1798   VoiceSenderInfo first_sender_info;
1799   InitVoiceSenderInfo(&first_sender_info, kFirstSsrc);
1800   UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &first_sender_info,
1801                                       false);
1802 
1803   VoiceSenderInfo second_sender_info;
1804   InitVoiceSenderInfo(&second_sender_info, kSecondSsrc);
1805   UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &second_sender_info,
1806                                       false);
1807 
1808   VoiceMediaInfo voice_info;
1809   voice_info.senders.push_back(first_sender_info);
1810   voice_info.senders.push_back(second_sender_info);
1811 
1812   auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1813   voice_media_channel->SetStats(voice_info);
1814 
1815   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1816 
1817   StatsReports reports;
1818   stats->GetStats(local_track.get(), &reports);
1819 
1820   // Both SSRC reports have the same track ID.
1821   EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1822                                reports, StatsReport::kStatsReportTypeSsrc,
1823                                StatsReport::kStatsValueNameTrackId, 1));
1824   EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1825                                reports, StatsReport::kStatsReportTypeSsrc,
1826                                StatsReport::kStatsValueNameTrackId, 2));
1827 
1828   // The SSRC in each SSRC report is different and correspond to the sender
1829   // SSRC.
1830   std::vector<absl::optional<std::string>> ssrcs = {
1831       GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1832                                 StatsReport::kStatsValueNameSsrc, 1),
1833       GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1834                                 StatsReport::kStatsValueNameSsrc, 2)};
1835   EXPECT_THAT(ssrcs, UnorderedElementsAre(rtc::ToString(kFirstSsrc),
1836                                           rtc::ToString(kSecondSsrc)));
1837 
1838   // There is one track report with the same track ID as the SSRC reports.
1839   EXPECT_EQ(
1840       1u, GetReportsByType(reports, StatsReport::kStatsReportTypeTrack).size());
1841   EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1842                                reports, StatsReport::kStatsReportTypeTrack,
1843                                StatsReport::kStatsValueNameTrackId, 1));
1844 }
1845 
1846 // This test verifies that stats are correctly set in video send ssrc stats.
TEST_P(StatsCollectorTrackTest,VerifyVideoSendSsrcStats)1847 TEST_P(StatsCollectorTrackTest, VerifyVideoSendSsrcStats) {
1848   auto pc = CreatePeerConnection();
1849   auto stats = CreateStatsCollector(pc.get());
1850 
1851   AddOutgoingVideoTrack(pc.get(), stats.get());
1852 
1853   VideoSenderInfo video_sender_info;
1854   video_sender_info.add_ssrc(1234);
1855   video_sender_info.frames_encoded = 10;
1856   video_sender_info.qp_sum = 11;
1857   VideoMediaInfo video_info;
1858   video_info.aggregated_senders.push_back(video_sender_info);
1859 
1860   pc->AddVideoChannel("video", "transport", video_info);
1861 
1862   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1863   StatsReports reports;
1864   stats->GetStats(nullptr, &reports);
1865 
1866   EXPECT_EQ(rtc::ToString(video_sender_info.frames_encoded),
1867             ExtractSsrcStatsValue(reports,
1868                                   StatsReport::kStatsValueNameFramesEncoded));
1869   EXPECT_EQ(rtc::ToString(*video_sender_info.qp_sum),
1870             ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
1871 }
1872 
1873 // This test verifies that stats are correctly set in video receive ssrc stats.
TEST_P(StatsCollectorTrackTest,VerifyVideoReceiveSsrcStatsNew)1874 TEST_P(StatsCollectorTrackTest, VerifyVideoReceiveSsrcStatsNew) {
1875   auto pc = CreatePeerConnection();
1876   auto stats = CreateStatsCollector(pc.get());
1877 
1878   AddIncomingVideoTrack(pc.get(), stats.get());
1879 
1880   VideoReceiverInfo video_receiver_info;
1881   video_receiver_info.add_ssrc(1234);
1882   video_receiver_info.frames_decoded = 10;
1883   video_receiver_info.qp_sum = 11;
1884   VideoMediaInfo video_info;
1885   video_info.receivers.push_back(video_receiver_info);
1886 
1887   pc->AddVideoChannel("video", "transport", video_info);
1888 
1889   stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1890   StatsReports reports;
1891   stats->GetStats(nullptr, &reports);
1892 
1893   EXPECT_EQ(rtc::ToString(video_receiver_info.frames_decoded),
1894             ExtractSsrcStatsValue(reports,
1895                                   StatsReport::kStatsValueNameFramesDecoded));
1896   EXPECT_EQ(rtc::ToString(*video_receiver_info.qp_sum),
1897             ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
1898 }
1899 
1900 INSTANTIATE_TEST_SUITE_P(HasStream, StatsCollectorTrackTest, ::testing::Bool());
1901 
1902 }  // namespace webrtc
1903