xref: /aosp_15_r20/external/webrtc/pc/rtc_stats_collector_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2016 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/rtc_stats_collector.h"
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <algorithm>
17 #include <initializer_list>
18 #include <memory>
19 #include <ostream>
20 #include <string>
21 #include <type_traits>
22 #include <utility>
23 #include <vector>
24 
25 #include "absl/strings/str_replace.h"
26 #include "api/candidate.h"
27 #include "api/dtls_transport_interface.h"
28 #include "api/media_stream_interface.h"
29 #include "api/media_stream_track.h"
30 #include "api/rtp_parameters.h"
31 #include "api/stats/rtc_stats.h"
32 #include "api/stats/rtc_stats_report.h"
33 #include "api/stats/rtcstats_objects.h"
34 #include "api/units/time_delta.h"
35 #include "api/units/timestamp.h"
36 #include "api/video/recordable_encoded_frame.h"
37 #include "api/video/video_content_type.h"
38 #include "api/video/video_frame.h"
39 #include "api/video/video_sink_interface.h"
40 #include "api/video/video_source_interface.h"
41 #include "api/video/video_timing.h"
42 #include "common_video/include/quality_limitation_reason.h"
43 #include "media/base/media_channel.h"
44 #include "modules/audio_processing/include/audio_processing_statistics.h"
45 #include "modules/rtp_rtcp/include/report_block_data.h"
46 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
47 #include "p2p/base/connection_info.h"
48 #include "p2p/base/ice_transport_internal.h"
49 #include "p2p/base/p2p_constants.h"
50 #include "p2p/base/port.h"
51 #include "pc/media_stream.h"
52 #include "pc/stream_collection.h"
53 #include "pc/test/fake_data_channel_controller.h"
54 #include "pc/test/fake_peer_connection_for_stats.h"
55 #include "pc/test/mock_data_channel.h"
56 #include "pc/test/mock_rtp_receiver_internal.h"
57 #include "pc/test/mock_rtp_sender_internal.h"
58 #include "pc/test/rtc_stats_obtainer.h"
59 #include "rtc_base/checks.h"
60 #include "rtc_base/fake_clock.h"
61 #include "rtc_base/fake_ssl_identity.h"
62 #include "rtc_base/gunit.h"
63 #include "rtc_base/network_constants.h"
64 #include "rtc_base/ref_counted_object.h"
65 #include "rtc_base/rtc_certificate.h"
66 #include "rtc_base/socket_address.h"
67 #include "rtc_base/ssl_fingerprint.h"
68 #include "rtc_base/ssl_identity.h"
69 #include "rtc_base/ssl_stream_adapter.h"
70 #include "rtc_base/string_encode.h"
71 #include "rtc_base/strings/json.h"
72 #include "rtc_base/synchronization/mutex.h"
73 #include "rtc_base/time_utils.h"
74 #include "test/gmock.h"
75 #include "test/gtest.h"
76 
77 using ::testing::_;
78 using ::testing::AtLeast;
79 using ::testing::Invoke;
80 using ::testing::Return;
81 
82 namespace webrtc {
83 
84 // These are used by gtest code, such as if `EXPECT_EQ` fails.
PrintTo(const RTCCertificateStats & stats,::std::ostream * os)85 void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
86   *os << stats.ToJson();
87 }
88 
PrintTo(const RTCCodecStats & stats,::std::ostream * os)89 void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
90   *os << stats.ToJson();
91 }
92 
PrintTo(const RTCDataChannelStats & stats,::std::ostream * os)93 void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
94   *os << stats.ToJson();
95 }
96 
PrintTo(const RTCIceCandidatePairStats & stats,::std::ostream * os)97 void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
98   *os << stats.ToJson();
99 }
100 
PrintTo(const RTCLocalIceCandidateStats & stats,::std::ostream * os)101 void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
102   *os << stats.ToJson();
103 }
104 
PrintTo(const RTCRemoteIceCandidateStats & stats,::std::ostream * os)105 void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
106   *os << stats.ToJson();
107 }
108 
PrintTo(const RTCPeerConnectionStats & stats,::std::ostream * os)109 void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
110   *os << stats.ToJson();
111 }
112 
PrintTo(const DEPRECATED_RTCMediaStreamStats & stats,::std::ostream * os)113 void PrintTo(const DEPRECATED_RTCMediaStreamStats& stats, ::std::ostream* os) {
114   *os << stats.ToJson();
115 }
116 
PrintTo(const DEPRECATED_RTCMediaStreamTrackStats & stats,::std::ostream * os)117 void PrintTo(const DEPRECATED_RTCMediaStreamTrackStats& stats,
118              ::std::ostream* os) {
119   *os << stats.ToJson();
120 }
121 
PrintTo(const RTCInboundRTPStreamStats & stats,::std::ostream * os)122 void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
123   *os << stats.ToJson();
124 }
125 
PrintTo(const RTCOutboundRTPStreamStats & stats,::std::ostream * os)126 void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
127   *os << stats.ToJson();
128 }
129 
PrintTo(const RTCRemoteInboundRtpStreamStats & stats,::std::ostream * os)130 void PrintTo(const RTCRemoteInboundRtpStreamStats& stats, ::std::ostream* os) {
131   *os << stats.ToJson();
132 }
133 
PrintTo(const RTCAudioSourceStats & stats,::std::ostream * os)134 void PrintTo(const RTCAudioSourceStats& stats, ::std::ostream* os) {
135   *os << stats.ToJson();
136 }
137 
PrintTo(const RTCVideoSourceStats & stats,::std::ostream * os)138 void PrintTo(const RTCVideoSourceStats& stats, ::std::ostream* os) {
139   *os << stats.ToJson();
140 }
141 
PrintTo(const RTCTransportStats & stats,::std::ostream * os)142 void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
143   *os << stats.ToJson();
144 }
145 
146 namespace {
147 
148 const int64_t kGetStatsReportTimeoutMs = 1000;
149 
150 // Fake data used by `SetupExampleStatsVoiceGraph()` to fill in remote outbound
151 // stats.
152 constexpr int64_t kRemoteOutboundStatsTimestampMs = 123;
153 constexpr int64_t kRemoteOutboundStatsRemoteTimestampMs = 456;
154 constexpr uint32_t kRemoteOutboundStatsPacketsSent = 7u;
155 constexpr uint64_t kRemoteOutboundStatsBytesSent = 8u;
156 constexpr uint64_t kRemoteOutboundStatsReportsCount = 9u;
157 
158 struct CertificateInfo {
159   rtc::scoped_refptr<rtc::RTCCertificate> certificate;
160   std::vector<std::string> ders;
161   std::vector<std::string> pems;
162   std::vector<std::string> fingerprints;
163 };
164 
165 // Return the ID for an object of the given type in a report.
166 // The object must be present and be unique.
167 template <typename T>
IdForType(const RTCStatsReport * report)168 std::string IdForType(const RTCStatsReport* report) {
169   auto stats_of_my_type = report->RTCStatsReport::GetStatsOfType<T>();
170   // We cannot use ASSERT here, since we're within a function.
171   EXPECT_EQ(1U, stats_of_my_type.size())
172       << "Unexpected number of stats of this type";
173   if (stats_of_my_type.size() == 1) {
174     return stats_of_my_type[0]->id();
175   } else {
176     // Return something that is not going to be a valid stas ID.
177     return "Type not found";
178   }
179 }
180 
CreateFakeCertificateAndInfoFromDers(const std::vector<std::string> & ders)181 std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
182     const std::vector<std::string>& ders) {
183   RTC_CHECK(!ders.empty());
184   std::unique_ptr<CertificateInfo> info(new CertificateInfo());
185   info->ders = ders;
186   for (const std::string& der : ders) {
187     info->pems.push_back(rtc::SSLIdentity::DerToPem(
188         "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
189         der.length()));
190   }
191   info->certificate =
192       rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
193           new rtc::FakeSSLIdentity(info->pems)));
194   // Strip header/footer and newline characters of PEM strings.
195   for (size_t i = 0; i < info->pems.size(); ++i) {
196     absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
197                          {"-----END CERTIFICATE-----", ""},
198                          {"\n", ""}},
199                         &info->pems[i]);
200   }
201   // Fingerprints for the whole certificate chain, starting with leaf
202   // certificate.
203   const rtc::SSLCertChain& chain = info->certificate->GetSSLCertificateChain();
204   std::unique_ptr<rtc::SSLFingerprint> fp;
205   for (size_t i = 0; i < chain.GetSize(); i++) {
206     fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
207     EXPECT_TRUE(fp);
208     info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
209   }
210   EXPECT_EQ(info->ders.size(), info->fingerprints.size());
211   return info;
212 }
213 
CreateFakeCandidate(const std::string & hostname,int port,const std::string & protocol,const rtc::AdapterType adapter_type,const std::string & candidate_type,uint32_t priority,const rtc::AdapterType underlying_type_for_vpn=rtc::ADAPTER_TYPE_UNKNOWN)214 std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
215     const std::string& hostname,
216     int port,
217     const std::string& protocol,
218     const rtc::AdapterType adapter_type,
219     const std::string& candidate_type,
220     uint32_t priority,
221     const rtc::AdapterType underlying_type_for_vpn =
222         rtc::ADAPTER_TYPE_UNKNOWN) {
223   std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
224   candidate->set_address(rtc::SocketAddress(hostname, port));
225   candidate->set_protocol(protocol);
226   candidate->set_network_type(adapter_type);
227   candidate->set_underlying_type_for_vpn(underlying_type_for_vpn);
228   candidate->set_type(candidate_type);
229   candidate->set_priority(priority);
230   // Defaults for testing.
231   candidate->set_foundation("foundationIsAString");
232   candidate->set_username("iceusernamefragment");
233   return candidate;
234 }
235 
236 class FakeAudioProcessor : public AudioProcessorInterface {
237  public:
FakeAudioProcessor()238   FakeAudioProcessor() {}
~FakeAudioProcessor()239   ~FakeAudioProcessor() {}
240 
241  private:
GetStats(bool has_recv_streams)242   AudioProcessorInterface::AudioProcessorStatistics GetStats(
243       bool has_recv_streams) override {
244     AudioProcessorStatistics stats;
245     stats.apm_statistics.echo_return_loss = 2.0;
246     stats.apm_statistics.echo_return_loss_enhancement = 3.0;
247     return stats;
248   }
249 };
250 
251 class FakeAudioTrackForStats : public MediaStreamTrack<AudioTrackInterface> {
252  public:
Create(const std::string & id,MediaStreamTrackInterface::TrackState state,bool create_fake_audio_processor)253   static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
254       const std::string& id,
255       MediaStreamTrackInterface::TrackState state,
256       bool create_fake_audio_processor) {
257     auto audio_track_stats = rtc::make_ref_counted<FakeAudioTrackForStats>(id);
258     audio_track_stats->set_state(state);
259     if (create_fake_audio_processor) {
260       audio_track_stats->processor_ =
261           rtc::make_ref_counted<FakeAudioProcessor>();
262     }
263     return audio_track_stats;
264   }
265 
FakeAudioTrackForStats(const std::string & id)266   explicit FakeAudioTrackForStats(const std::string& id)
267       : MediaStreamTrack<AudioTrackInterface>(id) {}
268 
kind() const269   std::string kind() const override {
270     return MediaStreamTrackInterface::kAudioKind;
271   }
GetSource() const272   webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
AddSink(webrtc::AudioTrackSinkInterface * sink)273   void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
RemoveSink(webrtc::AudioTrackSinkInterface * sink)274   void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)275   bool GetSignalLevel(int* level) override { return false; }
GetAudioProcessor()276   rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
277     return processor_;
278   }
279 
280  private:
281   rtc::scoped_refptr<FakeAudioProcessor> processor_;
282 };
283 
284 class FakeVideoTrackSourceForStats : public VideoTrackSourceInterface {
285  public:
Create(int input_width,int input_height)286   static rtc::scoped_refptr<FakeVideoTrackSourceForStats> Create(
287       int input_width,
288       int input_height) {
289     return rtc::make_ref_counted<FakeVideoTrackSourceForStats>(input_width,
290                                                                input_height);
291   }
292 
FakeVideoTrackSourceForStats(int input_width,int input_height)293   FakeVideoTrackSourceForStats(int input_width, int input_height)
294       : input_width_(input_width), input_height_(input_height) {}
~FakeVideoTrackSourceForStats()295   ~FakeVideoTrackSourceForStats() override {}
296 
297   // VideoTrackSourceInterface
is_screencast() const298   bool is_screencast() const override { return false; }
needs_denoising() const299   absl::optional<bool> needs_denoising() const override { return false; }
GetStats(VideoTrackSourceInterface::Stats * stats)300   bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
301     stats->input_width = input_width_;
302     stats->input_height = input_height_;
303     return true;
304   }
305   // MediaSourceInterface (part of VideoTrackSourceInterface)
state() const306   MediaSourceInterface::SourceState state() const override {
307     return MediaSourceInterface::SourceState::kLive;
308   }
remote() const309   bool remote() const override { return false; }
310   // NotifierInterface (part of MediaSourceInterface)
RegisterObserver(ObserverInterface * observer)311   void RegisterObserver(ObserverInterface* observer) override {}
UnregisterObserver(ObserverInterface * observer)312   void UnregisterObserver(ObserverInterface* observer) override {}
313   // rtc::VideoSourceInterface<VideoFrame> (part of VideoTrackSourceInterface)
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)314   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
315                        const rtc::VideoSinkWants& wants) override {}
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)316   void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
SupportsEncodedOutput() const317   bool SupportsEncodedOutput() const override { return false; }
GenerateKeyFrame()318   void GenerateKeyFrame() override {}
AddEncodedSink(rtc::VideoSinkInterface<RecordableEncodedFrame> * sink)319   void AddEncodedSink(
320       rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
RemoveEncodedSink(rtc::VideoSinkInterface<RecordableEncodedFrame> * sink)321   void RemoveEncodedSink(
322       rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
323 
324  private:
325   int input_width_;
326   int input_height_;
327 };
328 
329 class FakeVideoTrackForStats : public MediaStreamTrack<VideoTrackInterface> {
330  public:
Create(const std::string & id,MediaStreamTrackInterface::TrackState state,rtc::scoped_refptr<VideoTrackSourceInterface> source)331   static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
332       const std::string& id,
333       MediaStreamTrackInterface::TrackState state,
334       rtc::scoped_refptr<VideoTrackSourceInterface> source) {
335     auto video_track =
336         rtc::make_ref_counted<FakeVideoTrackForStats>(id, std::move(source));
337     video_track->set_state(state);
338     return video_track;
339   }
340 
FakeVideoTrackForStats(const std::string & id,rtc::scoped_refptr<VideoTrackSourceInterface> source)341   FakeVideoTrackForStats(const std::string& id,
342                          rtc::scoped_refptr<VideoTrackSourceInterface> source)
343       : MediaStreamTrack<VideoTrackInterface>(id), source_(source) {}
344 
kind() const345   std::string kind() const override {
346     return MediaStreamTrackInterface::kVideoKind;
347   }
348 
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)349   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
350                        const rtc::VideoSinkWants& wants) override {}
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)351   void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
352 
GetSource() const353   VideoTrackSourceInterface* GetSource() const override {
354     return source_.get();
355   }
356 
357  private:
358   rtc::scoped_refptr<VideoTrackSourceInterface> source_;
359 };
360 
CreateFakeTrack(cricket::MediaType media_type,const std::string & track_id,MediaStreamTrackInterface::TrackState track_state,bool create_fake_audio_processor=false)361 rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
362     cricket::MediaType media_type,
363     const std::string& track_id,
364     MediaStreamTrackInterface::TrackState track_state,
365     bool create_fake_audio_processor = false) {
366   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
367     return FakeAudioTrackForStats::Create(track_id, track_state,
368                                           create_fake_audio_processor);
369   } else {
370     RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
371     return FakeVideoTrackForStats::Create(track_id, track_state, nullptr);
372   }
373 }
374 
CreateMockSender(cricket::MediaType media_type,rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc,int attachment_id,std::vector<std::string> local_stream_ids)375 rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
376     cricket::MediaType media_type,
377     rtc::scoped_refptr<MediaStreamTrackInterface> track,
378     uint32_t ssrc,
379     int attachment_id,
380     std::vector<std::string> local_stream_ids) {
381   RTC_DCHECK(!track ||
382              (track->kind() == MediaStreamTrackInterface::kAudioKind &&
383               media_type == cricket::MEDIA_TYPE_AUDIO) ||
384              (track->kind() == MediaStreamTrackInterface::kVideoKind &&
385               media_type == cricket::MEDIA_TYPE_VIDEO));
386   auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
387   EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
388   EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
389   EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type));
390   EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
391     RtpParameters params;
392     params.encodings.push_back(RtpEncodingParameters());
393     params.encodings[0].ssrc = ssrc;
394     return params;
395   }));
396   EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
397   EXPECT_CALL(*sender, stream_ids()).WillRepeatedly(Return(local_stream_ids));
398   EXPECT_CALL(*sender, SetTransceiverAsStopped());
399   return sender;
400 }
401 
CreateMockReceiver(const rtc::scoped_refptr<MediaStreamTrackInterface> & track,uint32_t ssrc,int attachment_id)402 rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
403     const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
404     uint32_t ssrc,
405     int attachment_id) {
406   auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
407   EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
408   EXPECT_CALL(*receiver, streams())
409       .WillRepeatedly(
410           Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>({})));
411 
412   EXPECT_CALL(*receiver, media_type())
413       .WillRepeatedly(
414           Return(track->kind() == MediaStreamTrackInterface::kAudioKind
415                      ? cricket::MEDIA_TYPE_AUDIO
416                      : cricket::MEDIA_TYPE_VIDEO));
417   EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
418     RtpParameters params;
419     params.encodings.push_back(RtpEncodingParameters());
420     params.encodings[0].ssrc = ssrc;
421     return params;
422   }));
423   EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
424   EXPECT_CALL(*receiver, Stop()).WillRepeatedly(Return());
425   return receiver;
426 }
427 
428 class RTCStatsCollectorWrapper {
429  public:
RTCStatsCollectorWrapper(rtc::scoped_refptr<FakePeerConnectionForStats> pc)430   explicit RTCStatsCollectorWrapper(
431       rtc::scoped_refptr<FakePeerConnectionForStats> pc)
432       : pc_(pc),
433         stats_collector_(
434             RTCStatsCollector::Create(pc.get(),
435                                       50 * rtc::kNumMicrosecsPerMillisec)) {}
436 
stats_collector()437   rtc::scoped_refptr<RTCStatsCollector> stats_collector() {
438     return stats_collector_;
439   }
440 
GetStatsReport()441   rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
442     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
443     stats_collector_->GetStatsReport(callback);
444     return WaitForReport(callback);
445   }
446 
GetStatsReportWithSenderSelector(rtc::scoped_refptr<RtpSenderInternal> selector)447   rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithSenderSelector(
448       rtc::scoped_refptr<RtpSenderInternal> selector) {
449     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
450     stats_collector_->GetStatsReport(selector, callback);
451     return WaitForReport(callback);
452   }
453 
GetStatsReportWithReceiverSelector(rtc::scoped_refptr<RtpReceiverInternal> selector)454   rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithReceiverSelector(
455       rtc::scoped_refptr<RtpReceiverInternal> selector) {
456     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
457     stats_collector_->GetStatsReport(selector, callback);
458     return WaitForReport(callback);
459   }
460 
GetFreshStatsReport()461   rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
462     stats_collector_->ClearCachedStatsReport();
463     return GetStatsReport();
464   }
465 
SetupLocalTrackAndSender(cricket::MediaType media_type,const std::string & track_id,uint32_t ssrc,bool add_stream,int attachment_id)466   rtc::scoped_refptr<MockRtpSenderInternal> SetupLocalTrackAndSender(
467       cricket::MediaType media_type,
468       const std::string& track_id,
469       uint32_t ssrc,
470       bool add_stream,
471       int attachment_id) {
472     rtc::scoped_refptr<MediaStream> local_stream;
473     if (add_stream) {
474       local_stream = MediaStream::Create("LocalStreamId");
475       pc_->mutable_local_streams()->AddStream(local_stream);
476     }
477 
478     rtc::scoped_refptr<MediaStreamTrackInterface> track;
479     if (media_type == cricket::MEDIA_TYPE_AUDIO) {
480       track = CreateFakeTrack(media_type, track_id,
481                               MediaStreamTrackInterface::kLive);
482       if (add_stream) {
483         local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
484             static_cast<AudioTrackInterface*>(track.get())));
485       }
486     } else {
487       track = CreateFakeTrack(media_type, track_id,
488                               MediaStreamTrackInterface::kLive);
489       if (add_stream) {
490         local_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
491             static_cast<VideoTrackInterface*>(track.get())));
492       }
493     }
494 
495     rtc::scoped_refptr<MockRtpSenderInternal> sender =
496         CreateMockSender(media_type, track, ssrc, attachment_id, {});
497     EXPECT_CALL(*sender, Stop());
498     EXPECT_CALL(*sender, SetMediaChannel(_));
499     pc_->AddSender(sender);
500     return sender;
501   }
502 
SetupRemoteTrackAndReceiver(cricket::MediaType media_type,const std::string & track_id,const std::string & stream_id,uint32_t ssrc)503   rtc::scoped_refptr<MockRtpReceiverInternal> SetupRemoteTrackAndReceiver(
504       cricket::MediaType media_type,
505       const std::string& track_id,
506       const std::string& stream_id,
507       uint32_t ssrc) {
508     rtc::scoped_refptr<MediaStream> remote_stream =
509         MediaStream::Create(stream_id);
510     pc_->mutable_remote_streams()->AddStream(remote_stream);
511 
512     rtc::scoped_refptr<MediaStreamTrackInterface> track;
513     if (media_type == cricket::MEDIA_TYPE_AUDIO) {
514       track = CreateFakeTrack(media_type, track_id,
515                               MediaStreamTrackInterface::kLive);
516       remote_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
517           static_cast<AudioTrackInterface*>(track.get())));
518     } else {
519       track = CreateFakeTrack(media_type, track_id,
520                               MediaStreamTrackInterface::kLive);
521       remote_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
522           static_cast<VideoTrackInterface*>(track.get())));
523     }
524 
525     rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
526         CreateMockReceiver(track, ssrc, 62);
527     EXPECT_CALL(*receiver, streams())
528         .WillRepeatedly(
529             Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
530                 {remote_stream})));
531     EXPECT_CALL(*receiver, SetMediaChannel(_)).WillRepeatedly(Return());
532     pc_->AddReceiver(receiver);
533     return receiver;
534   }
535 
536   // Attaches tracks to peer connections by configuring RTP senders and RTP
537   // receivers according to the tracks' pairings with
538   // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
539   // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
540   // be associated with one |[Voice/Video]ReceiverInfo|.
541   // Senders get assigned attachment ID "ssrc + 10".
CreateMockRtpSendersReceiversAndChannels(std::initializer_list<std::pair<MediaStreamTrackInterface *,cricket::VoiceSenderInfo>> local_audio_track_info_pairs,std::initializer_list<std::pair<MediaStreamTrackInterface *,cricket::VoiceReceiverInfo>> remote_audio_track_info_pairs,std::initializer_list<std::pair<MediaStreamTrackInterface *,cricket::VideoSenderInfo>> local_video_track_info_pairs,std::initializer_list<std::pair<MediaStreamTrackInterface *,cricket::VideoReceiverInfo>> remote_video_track_info_pairs,std::vector<std::string> local_stream_ids,std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams)542   void CreateMockRtpSendersReceiversAndChannels(
543       std::initializer_list<
544           std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
545           local_audio_track_info_pairs,
546       std::initializer_list<
547           std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
548           remote_audio_track_info_pairs,
549       std::initializer_list<
550           std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
551           local_video_track_info_pairs,
552       std::initializer_list<
553           std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
554           remote_video_track_info_pairs,
555       std::vector<std::string> local_stream_ids,
556       std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
557     cricket::VoiceMediaInfo voice_media_info;
558     cricket::VideoMediaInfo video_media_info;
559 
560     // Local audio tracks and voice sender infos
561     for (auto& pair : local_audio_track_info_pairs) {
562       MediaStreamTrackInterface* local_audio_track = pair.first;
563       const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
564       RTC_DCHECK_EQ(local_audio_track->kind(),
565                     MediaStreamTrackInterface::kAudioKind);
566 
567       voice_media_info.senders.push_back(voice_sender_info);
568       rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
569           cricket::MEDIA_TYPE_AUDIO,
570           rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
571           voice_sender_info.local_stats[0].ssrc,
572           voice_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
573       EXPECT_CALL(*rtp_sender, SetMediaChannel(_)).WillRepeatedly(Return());
574       EXPECT_CALL(*rtp_sender, Stop());
575       pc_->AddSender(rtp_sender);
576     }
577 
578     // Remote audio tracks and voice receiver infos
579     for (auto& pair : remote_audio_track_info_pairs) {
580       MediaStreamTrackInterface* remote_audio_track = pair.first;
581       const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
582       RTC_DCHECK_EQ(remote_audio_track->kind(),
583                     MediaStreamTrackInterface::kAudioKind);
584 
585       voice_media_info.receivers.push_back(voice_receiver_info);
586       rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
587           CreateMockReceiver(
588               rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
589               voice_receiver_info.local_stats[0].ssrc,
590               voice_receiver_info.local_stats[0].ssrc + 10);
591       EXPECT_CALL(*rtp_receiver, streams())
592           .WillRepeatedly(Return(remote_streams));
593       EXPECT_CALL(*rtp_receiver, SetMediaChannel(_)).WillRepeatedly(Return());
594       pc_->AddReceiver(rtp_receiver);
595     }
596 
597     // Local video tracks and video sender infos
598     for (auto& pair : local_video_track_info_pairs) {
599       MediaStreamTrackInterface* local_video_track = pair.first;
600       const cricket::VideoSenderInfo& video_sender_info = pair.second;
601       RTC_DCHECK_EQ(local_video_track->kind(),
602                     MediaStreamTrackInterface::kVideoKind);
603 
604       video_media_info.senders.push_back(video_sender_info);
605       video_media_info.aggregated_senders.push_back(video_sender_info);
606       rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
607           cricket::MEDIA_TYPE_VIDEO,
608           rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
609           video_sender_info.local_stats[0].ssrc,
610           video_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
611       EXPECT_CALL(*rtp_sender, SetMediaChannel(_)).WillRepeatedly(Return());
612       EXPECT_CALL(*rtp_sender, Stop());
613       pc_->AddSender(rtp_sender);
614     }
615 
616     // Remote video tracks and video receiver infos
617     for (auto& pair : remote_video_track_info_pairs) {
618       MediaStreamTrackInterface* remote_video_track = pair.first;
619       const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
620       RTC_DCHECK_EQ(remote_video_track->kind(),
621                     MediaStreamTrackInterface::kVideoKind);
622 
623       video_media_info.receivers.push_back(video_receiver_info);
624       rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
625           CreateMockReceiver(
626               rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
627               video_receiver_info.local_stats[0].ssrc,
628               video_receiver_info.local_stats[0].ssrc + 10);
629       EXPECT_CALL(*rtp_receiver, streams())
630           .WillRepeatedly(Return(remote_streams));
631       EXPECT_CALL(*rtp_receiver, SetMediaChannel(_)).WillRepeatedly(Return());
632       pc_->AddReceiver(rtp_receiver);
633     }
634 
635     pc_->AddVoiceChannel("audio", "transport", voice_media_info);
636     pc_->AddVideoChannel("video", "transport", video_media_info);
637   }
638 
639  private:
WaitForReport(rtc::scoped_refptr<RTCStatsObtainer> callback)640   rtc::scoped_refptr<const RTCStatsReport> WaitForReport(
641       rtc::scoped_refptr<RTCStatsObtainer> callback) {
642     EXPECT_TRUE_WAIT(callback->report() != nullptr, kGetStatsReportTimeoutMs);
643     int64_t after = rtc::TimeUTCMicros();
644     for (const RTCStats& stats : *callback->report()) {
645       if (stats.type() == RTCRemoteInboundRtpStreamStats::kType ||
646           stats.type() == RTCRemoteOutboundRtpStreamStats::kType) {
647         // Ignore remote timestamps.
648         continue;
649       }
650       EXPECT_LE(stats.timestamp_us(), after);
651     }
652     return callback->report();
653   }
654 
655   rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
656   rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
657 };
658 
659 class RTCStatsCollectorTest : public ::testing::Test {
660  public:
RTCStatsCollectorTest()661   RTCStatsCollectorTest()
662       : pc_(rtc::make_ref_counted<FakePeerConnectionForStats>()),
663         stats_(new RTCStatsCollectorWrapper(pc_)) {}
664 
ExpectReportContainsCertificateInfo(const rtc::scoped_refptr<const RTCStatsReport> & report,const CertificateInfo & certinfo)665   void ExpectReportContainsCertificateInfo(
666       const rtc::scoped_refptr<const RTCStatsReport>& report,
667       const CertificateInfo& certinfo) {
668     for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
669       RTCCertificateStats expected_certificate_stats(
670           "CF" + certinfo.fingerprints[i], report->timestamp_us());
671       expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
672       expected_certificate_stats.fingerprint_algorithm = "sha-1";
673       expected_certificate_stats.base64_certificate = certinfo.pems[i];
674       if (i + 1 < certinfo.fingerprints.size()) {
675         expected_certificate_stats.issuer_certificate_id =
676             "CF" + certinfo.fingerprints[i + 1];
677       }
678       ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
679       EXPECT_EQ(expected_certificate_stats,
680                 report->Get(expected_certificate_stats.id())
681                     ->cast_to<RTCCertificateStats>());
682     }
683   }
684 
GetCertificateStatsFromFingerprint(const rtc::scoped_refptr<const RTCStatsReport> & report,const std::string & fingerprint)685   const RTCCertificateStats* GetCertificateStatsFromFingerprint(
686       const rtc::scoped_refptr<const RTCStatsReport>& report,
687       const std::string& fingerprint) {
688     auto certificates = report->GetStatsOfType<RTCCertificateStats>();
689     for (const auto* certificate : certificates) {
690       if (*certificate->fingerprint == fingerprint) {
691         return certificate;
692       }
693     }
694     return nullptr;
695   }
696 
697   struct ExampleStatsGraph {
698     rtc::scoped_refptr<RtpSenderInternal> sender;
699     rtc::scoped_refptr<RtpReceiverInternal> receiver;
700 
701     rtc::scoped_refptr<const RTCStatsReport> full_report;
702     std::string send_codec_id;
703     std::string recv_codec_id;
704     std::string outbound_rtp_id;
705     std::string inbound_rtp_id;
706     std::string remote_outbound_rtp_id;
707     std::string transport_id;
708     std::string sender_track_id;
709     std::string receiver_track_id;
710     std::string remote_stream_id;
711     std::string peer_connection_id;
712     std::string media_source_id;
713   };
714 
715   // Sets up the example stats graph (see ASCII art below) for a video only
716   // call. The graph is used for testing the stats selection algorithm (see
717   // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm).
718   // These tests test the integration of the stats traversal algorithm inside of
719   // RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
720   // traversal tests.
SetupExampleStatsGraphForSelectorTests()721   ExampleStatsGraph SetupExampleStatsGraphForSelectorTests() {
722     ExampleStatsGraph graph;
723 
724     // codec (send)
725     graph.send_codec_id = "COTTransportName1_1";
726     cricket::VideoMediaInfo video_media_info;
727     RtpCodecParameters send_codec;
728     send_codec.payload_type = 1;
729     send_codec.clock_rate = 0;
730     video_media_info.send_codecs.insert(
731         std::make_pair(send_codec.payload_type, send_codec));
732     // codec (recv)
733     graph.recv_codec_id = "CITTransportName1_2";
734     RtpCodecParameters recv_codec;
735     recv_codec.payload_type = 2;
736     recv_codec.clock_rate = 0;
737     video_media_info.receive_codecs.insert(
738         std::make_pair(recv_codec.payload_type, recv_codec));
739     // outbound-rtp
740     graph.outbound_rtp_id = "OTTransportName1V3";
741     video_media_info.senders.push_back(cricket::VideoSenderInfo());
742     video_media_info.senders[0].local_stats.push_back(
743         cricket::SsrcSenderInfo());
744     video_media_info.senders[0].local_stats[0].ssrc = 3;
745     video_media_info.senders[0].codec_payload_type = send_codec.payload_type;
746     video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
747     // inbound-rtp
748     graph.inbound_rtp_id = "ITTransportName1V4";
749     video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
750     video_media_info.receivers[0].local_stats.push_back(
751         cricket::SsrcReceiverInfo());
752     video_media_info.receivers[0].local_stats[0].ssrc = 4;
753     video_media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
754     // transport
755     graph.transport_id = "TTransportName1";
756     pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
757     // track (sender)
758     graph.sender = stats_->SetupLocalTrackAndSender(
759         cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false, 50);
760     graph.sender_track_id =
761         "DEPRECATED_TO" + rtc::ToString(graph.sender->AttachmentId());
762     // track (receiver) and stream (remote stream)
763     graph.receiver = stats_->SetupRemoteTrackAndReceiver(
764         cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
765     graph.receiver_track_id =
766         "DEPRECATED_TI" + rtc::ToString(graph.receiver->AttachmentId());
767     graph.remote_stream_id = "DEPRECATED_SRemoteStreamId";
768     // peer-connection
769     graph.peer_connection_id = "P";
770     // media-source (kind: video)
771     graph.media_source_id = "SV" + rtc::ToString(graph.sender->AttachmentId());
772 
773     // Expected stats graph:
774     //
775     //  +--- track (sender)      stream (remote stream) ---> track (receiver)
776     //  |             ^                                        ^
777     //  |             |                                        |
778     //  | +--------- outbound-rtp   inbound-rtp ---------------+
779     //  | |           |        |     |       |
780     //  | |           v        v     v       v
781     //  | |  codec (send)     transport     codec (recv)     peer-connection
782     //  v v
783     //  media-source
784 
785     // Verify the stats graph is set up correctly.
786     graph.full_report = stats_->GetStatsReport();
787     EXPECT_EQ(graph.full_report->size(), 10u);
788     EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
789     EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
790     EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
791     EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
792     EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
793     EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
794     EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
795     EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
796     EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
797     EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
798     const auto& sender_track =
799         graph.full_report->Get(graph.sender_track_id)
800             ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>();
801     EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
802     const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
803                                    ->cast_to<RTCOutboundRTPStreamStats>();
804     EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
805     EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
806     EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
807     EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
808     const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
809                                   ->cast_to<RTCInboundRTPStreamStats>();
810     EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
811     EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
812     EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
813 
814     return graph;
815   }
816 
817   // Sets up an example stats graph (see ASCII art below) for an audio only call
818   // and checks that the expected stats are generated.
SetupExampleStatsVoiceGraph(bool add_remote_outbound_stats)819   ExampleStatsGraph SetupExampleStatsVoiceGraph(
820       bool add_remote_outbound_stats) {
821     constexpr uint32_t kLocalSsrc = 3;
822     constexpr uint32_t kRemoteSsrc = 4;
823     ExampleStatsGraph graph;
824 
825     // codec (send)
826     graph.send_codec_id = "COTTransportName1_1";
827     cricket::VoiceMediaInfo media_info;
828     RtpCodecParameters send_codec;
829     send_codec.payload_type = 1;
830     send_codec.clock_rate = 0;
831     media_info.send_codecs.insert(
832         std::make_pair(send_codec.payload_type, send_codec));
833     // codec (recv)
834     graph.recv_codec_id = "CITTransportName1_2";
835     RtpCodecParameters recv_codec;
836     recv_codec.payload_type = 2;
837     recv_codec.clock_rate = 0;
838     media_info.receive_codecs.insert(
839         std::make_pair(recv_codec.payload_type, recv_codec));
840     // outbound-rtp
841     graph.outbound_rtp_id = "OTTransportName1A3";
842     media_info.senders.push_back(cricket::VoiceSenderInfo());
843     media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
844     media_info.senders[0].local_stats[0].ssrc = kLocalSsrc;
845     media_info.senders[0].codec_payload_type = send_codec.payload_type;
846     // inbound-rtp
847     graph.inbound_rtp_id = "ITTransportName1A4";
848     media_info.receivers.push_back(cricket::VoiceReceiverInfo());
849     media_info.receivers[0].local_stats.push_back(cricket::SsrcReceiverInfo());
850     media_info.receivers[0].local_stats[0].ssrc = kRemoteSsrc;
851     media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
852     // remote-outbound-rtp
853     if (add_remote_outbound_stats) {
854       graph.remote_outbound_rtp_id = "ROA4";
855       media_info.receivers[0].last_sender_report_timestamp_ms =
856           kRemoteOutboundStatsTimestampMs;
857       media_info.receivers[0].last_sender_report_remote_timestamp_ms =
858           kRemoteOutboundStatsRemoteTimestampMs;
859       media_info.receivers[0].sender_reports_packets_sent =
860           kRemoteOutboundStatsPacketsSent;
861       media_info.receivers[0].sender_reports_bytes_sent =
862           kRemoteOutboundStatsBytesSent;
863       media_info.receivers[0].sender_reports_reports_count =
864           kRemoteOutboundStatsReportsCount;
865     }
866 
867     // transport
868     graph.transport_id = "TTransportName1";
869     pc_->AddVoiceChannel("VoiceMid", "TransportName", media_info);
870     // track (sender)
871     graph.sender = stats_->SetupLocalTrackAndSender(
872         cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", kLocalSsrc, false, 50);
873     graph.sender_track_id =
874         "DEPRECATED_TO" + rtc::ToString(graph.sender->AttachmentId());
875     // track (receiver) and stream (remote stream)
876     graph.receiver = stats_->SetupRemoteTrackAndReceiver(
877         cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId",
878         kRemoteSsrc);
879     graph.receiver_track_id =
880         "DEPRECATED_TI" + rtc::ToString(graph.receiver->AttachmentId());
881     graph.remote_stream_id = "DEPRECATED_SRemoteStreamId";
882     // peer-connection
883     graph.peer_connection_id = "P";
884     // media-source (kind: video)
885     graph.media_source_id = "SA" + rtc::ToString(graph.sender->AttachmentId());
886 
887     // Expected stats graph:
888     //
889     //  +--- track (sender)      stream (remote stream) ---> track (receiver)
890     //  |             ^                                        ^
891     //  |             |                                        |
892     //  | +--------- outbound-rtp   inbound-rtp ---------------+
893     //  | |           |        |     |       |
894     //  | |           v        v     v       v
895     //  | |  codec (send)     transport     codec (recv)     peer-connection
896     //  v v
897     //  media-source
898 
899     // Verify the stats graph is set up correctly.
900     graph.full_report = stats_->GetStatsReport();
901     EXPECT_EQ(graph.full_report->size(), add_remote_outbound_stats ? 11u : 10u);
902     EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
903     EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
904     EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
905     EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
906     EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
907     EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
908     EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
909     EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
910     EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
911     EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
912     // `graph.remote_outbound_rtp_id` is omitted on purpose so that expectations
913     // can be added by the caller depending on what value it sets for the
914     // `add_remote_outbound_stats` argument.
915     const auto& sender_track =
916         graph.full_report->Get(graph.sender_track_id)
917             ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>();
918     EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
919     const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
920                                    ->cast_to<RTCOutboundRTPStreamStats>();
921     EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
922     EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
923     EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
924     EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
925     const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
926                                   ->cast_to<RTCInboundRTPStreamStats>();
927     EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
928     EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
929     EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
930 
931     return graph;
932   }
933 
934  protected:
935   rtc::ScopedFakeClock fake_clock_;
936   rtc::AutoThread main_thread_;
937   rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
938   std::unique_ptr<RTCStatsCollectorWrapper> stats_;
939 };
940 
TEST_F(RTCStatsCollectorTest,SingleCallback)941 TEST_F(RTCStatsCollectorTest, SingleCallback) {
942   rtc::scoped_refptr<const RTCStatsReport> result;
943   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
944   EXPECT_TRUE_WAIT(result != nullptr, kGetStatsReportTimeoutMs);
945 }
946 
TEST_F(RTCStatsCollectorTest,MultipleCallbacks)947 TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
948   rtc::scoped_refptr<const RTCStatsReport> a, b, c;
949   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
950   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
951   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
952   EXPECT_TRUE_WAIT(a != nullptr, kGetStatsReportTimeoutMs);
953   EXPECT_TRUE_WAIT(b != nullptr, kGetStatsReportTimeoutMs);
954   EXPECT_TRUE_WAIT(c != nullptr, kGetStatsReportTimeoutMs);
955 
956   EXPECT_EQ(a.get(), b.get());
957   EXPECT_EQ(b.get(), c.get());
958 }
959 
TEST_F(RTCStatsCollectorTest,CachedStatsReports)960 TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
961   // Caching should ensure `a` and `b` are the same report.
962   rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
963   rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
964   EXPECT_EQ(a.get(), b.get());
965   // Invalidate cache by clearing it.
966   stats_->stats_collector()->ClearCachedStatsReport();
967   rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
968   EXPECT_NE(b.get(), c.get());
969   // Invalidate cache by advancing time.
970   fake_clock_.AdvanceTime(TimeDelta::Millis(51));
971   rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
972   EXPECT_TRUE(d);
973   EXPECT_NE(c.get(), d.get());
974 }
975 
TEST_F(RTCStatsCollectorTest,MultipleCallbacksWithInvalidatedCacheInBetween)976 TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
977   rtc::scoped_refptr<const RTCStatsReport> a, b, c;
978   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
979   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
980   // Cache is invalidated after 50 ms.
981   fake_clock_.AdvanceTime(TimeDelta::Millis(51));
982   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
983   EXPECT_TRUE_WAIT(a != nullptr, kGetStatsReportTimeoutMs);
984   EXPECT_TRUE_WAIT(b != nullptr, kGetStatsReportTimeoutMs);
985   EXPECT_TRUE_WAIT(c != nullptr, kGetStatsReportTimeoutMs);
986   EXPECT_EQ(a.get(), b.get());
987   // The act of doing `AdvanceTime` processes all messages. If this was not the
988   // case we might not require `c` to be fresher than `b`.
989   EXPECT_NE(c.get(), b.get());
990 }
991 
TEST_F(RTCStatsCollectorTest,ToJsonProducesParseableJson)992 TEST_F(RTCStatsCollectorTest, ToJsonProducesParseableJson) {
993   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
994   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
995   std::string json_format = report->ToJson();
996 
997   Json::CharReaderBuilder builder;
998   Json::Value json_value;
999   std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
1000   ASSERT_TRUE(reader->parse(json_format.c_str(),
1001                             json_format.c_str() + json_format.size(),
1002                             &json_value, nullptr));
1003 
1004   // A very brief sanity check on the result.
1005   EXPECT_EQ(report->size(), json_value.size());
1006 }
1007 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsSingle)1008 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
1009   const char kTransportName[] = "transport";
1010 
1011   pc_->AddVoiceChannel("audio", kTransportName);
1012 
1013   std::unique_ptr<CertificateInfo> local_certinfo =
1014       CreateFakeCertificateAndInfoFromDers(
1015           std::vector<std::string>({"(local) single certificate"}));
1016   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
1017 
1018   std::unique_ptr<CertificateInfo> remote_certinfo =
1019       CreateFakeCertificateAndInfoFromDers(
1020           std::vector<std::string>({"(remote) single certificate"}));
1021   pc_->SetRemoteCertChain(
1022       kTransportName,
1023       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1024 
1025   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1026 
1027   ExpectReportContainsCertificateInfo(report, *local_certinfo);
1028   ExpectReportContainsCertificateInfo(report, *remote_certinfo);
1029 }
1030 
1031 // These SSRC collisions are legal.
TEST_F(RTCStatsCollectorTest,ValidSsrcCollisionDoesNotCrash)1032 TEST_F(RTCStatsCollectorTest, ValidSsrcCollisionDoesNotCrash) {
1033   // BUNDLE audio/video inbound/outbound. Unique SSRCs needed within the BUNDLE.
1034   cricket::VoiceMediaInfo mid1_info;
1035   mid1_info.receivers.emplace_back();
1036   mid1_info.receivers[0].add_ssrc(1);
1037   mid1_info.senders.emplace_back();
1038   mid1_info.senders[0].add_ssrc(2);
1039   pc_->AddVoiceChannel("Mid1", "Transport1", mid1_info);
1040   cricket::VideoMediaInfo mid2_info;
1041   mid2_info.receivers.emplace_back();
1042   mid2_info.receivers[0].add_ssrc(3);
1043   mid2_info.senders.emplace_back();
1044   mid2_info.senders[0].add_ssrc(4);
1045   pc_->AddVideoChannel("Mid2", "Transport1", mid2_info);
1046   // Now create a second BUNDLE group with SSRCs colliding with the first group
1047   // (but again no collisions within the group).
1048   cricket::VoiceMediaInfo mid3_info;
1049   mid3_info.receivers.emplace_back();
1050   mid3_info.receivers[0].add_ssrc(1);
1051   mid3_info.senders.emplace_back();
1052   mid3_info.senders[0].add_ssrc(2);
1053   pc_->AddVoiceChannel("Mid3", "Transport2", mid3_info);
1054   cricket::VideoMediaInfo mid4_info;
1055   mid4_info.receivers.emplace_back();
1056   mid4_info.receivers[0].add_ssrc(3);
1057   mid4_info.senders.emplace_back();
1058   mid4_info.senders[0].add_ssrc(4);
1059   pc_->AddVideoChannel("Mid4", "Transport2", mid4_info);
1060 
1061   // This should not crash (https://crbug.com/1361612).
1062   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1063   auto inbound_rtps = report->GetStatsOfType<RTCInboundRTPStreamStats>();
1064   auto outbound_rtps = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
1065   EXPECT_EQ(inbound_rtps.size(), 4u);
1066   EXPECT_EQ(outbound_rtps.size(), 4u);
1067 }
1068 
1069 // These SSRC collisions are illegal, so it is not clear if this setup can
1070 // happen even when talking to a malicious endpoint, but simulate illegal SSRC
1071 // collisions just to make sure we don't crash in even the most extreme cases.
TEST_F(RTCStatsCollectorTest,InvalidSsrcCollisionDoesNotCrash)1072 TEST_F(RTCStatsCollectorTest, InvalidSsrcCollisionDoesNotCrash) {
1073   // One SSRC to rule them all.
1074   cricket::VoiceMediaInfo mid1_info;
1075   mid1_info.receivers.emplace_back();
1076   mid1_info.receivers[0].add_ssrc(1);
1077   mid1_info.senders.emplace_back();
1078   mid1_info.senders[0].add_ssrc(1);
1079   pc_->AddVoiceChannel("Mid1", "BundledTransport", mid1_info);
1080   cricket::VideoMediaInfo mid2_info;
1081   mid2_info.receivers.emplace_back();
1082   mid2_info.receivers[0].add_ssrc(1);
1083   mid2_info.senders.emplace_back();
1084   mid2_info.senders[0].add_ssrc(1);
1085   pc_->AddVideoChannel("Mid2", "BundledTransport", mid2_info);
1086   cricket::VoiceMediaInfo mid3_info;
1087   mid3_info.receivers.emplace_back();
1088   mid3_info.receivers[0].add_ssrc(1);
1089   mid3_info.senders.emplace_back();
1090   mid3_info.senders[0].add_ssrc(1);
1091   pc_->AddVoiceChannel("Mid3", "BundledTransport", mid3_info);
1092   cricket::VideoMediaInfo mid4_info;
1093   mid4_info.receivers.emplace_back();
1094   mid4_info.receivers[0].add_ssrc(1);
1095   mid4_info.senders.emplace_back();
1096   mid4_info.senders[0].add_ssrc(1);
1097   pc_->AddVideoChannel("Mid4", "BundledTransport", mid4_info);
1098 
1099   // This should not crash (https://crbug.com/1361612).
1100   stats_->GetStatsReport();
1101   // Because this setup is illegal, there is no "right answer" to how the report
1102   // should look. We only care about not crashing.
1103 }
1104 
TEST_F(RTCStatsCollectorTest,CollectRTCCodecStatsOnlyIfReferenced)1105 TEST_F(RTCStatsCollectorTest, CollectRTCCodecStatsOnlyIfReferenced) {
1106   // Audio
1107   cricket::VoiceMediaInfo voice_media_info;
1108 
1109   RtpCodecParameters inbound_audio_codec;
1110   inbound_audio_codec.payload_type = 1;
1111   inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
1112   inbound_audio_codec.name = "opus";
1113   inbound_audio_codec.clock_rate = 1337;
1114   inbound_audio_codec.num_channels = 1;
1115   inbound_audio_codec.parameters = {{"minptime", "10"}, {"useinbandfec", "1"}};
1116   voice_media_info.receive_codecs.insert(
1117       std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
1118 
1119   RtpCodecParameters outbound_audio_codec;
1120   outbound_audio_codec.payload_type = 2;
1121   outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
1122   outbound_audio_codec.name = "isac";
1123   outbound_audio_codec.clock_rate = 1338;
1124   outbound_audio_codec.num_channels = 2;
1125   voice_media_info.send_codecs.insert(
1126       std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
1127 
1128   // Video
1129   cricket::VideoMediaInfo video_media_info;
1130 
1131   RtpCodecParameters inbound_video_codec;
1132   inbound_video_codec.payload_type = 3;
1133   inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
1134   inbound_video_codec.name = "H264";
1135   inbound_video_codec.clock_rate = 1339;
1136   inbound_video_codec.parameters = {{"level-asymmetry-allowed", "1"},
1137                                     {"packetization-mode", "1"},
1138                                     {"profile-level-id", "42001f"}};
1139   video_media_info.receive_codecs.insert(
1140       std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
1141 
1142   RtpCodecParameters outbound_video_codec;
1143   outbound_video_codec.payload_type = 4;
1144   outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
1145   outbound_video_codec.name = "VP8";
1146   outbound_video_codec.clock_rate = 1340;
1147   video_media_info.send_codecs.insert(
1148       std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
1149 
1150   // Ensure the above codecs are referenced.
1151   cricket::VoiceReceiverInfo inbound_audio_info;
1152   inbound_audio_info.add_ssrc(10);
1153   inbound_audio_info.codec_payload_type = 1;
1154   voice_media_info.receivers.push_back(inbound_audio_info);
1155 
1156   cricket::VoiceSenderInfo outbound_audio_info;
1157   outbound_audio_info.add_ssrc(20);
1158   outbound_audio_info.codec_payload_type = 2;
1159   voice_media_info.senders.push_back(outbound_audio_info);
1160 
1161   cricket::VideoReceiverInfo inbound_video_info;
1162   inbound_video_info.add_ssrc(30);
1163   inbound_video_info.codec_payload_type = 3;
1164   video_media_info.receivers.push_back(inbound_video_info);
1165 
1166   cricket::VideoSenderInfo outbound_video_info;
1167   outbound_video_info.add_ssrc(40);
1168   outbound_video_info.codec_payload_type = 4;
1169   video_media_info.senders.push_back(outbound_video_info);
1170 
1171   FakeVoiceMediaChannelForStats* audio_channel =
1172       pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
1173   FakeVideoMediaChannelForStats* video_channel =
1174       pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
1175 
1176   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1177 
1178   RTCCodecStats expected_inbound_audio_codec(
1179       "CITTransportName1_1_minptime=10;useinbandfec=1", report->timestamp_us());
1180   expected_inbound_audio_codec.payload_type = 1;
1181   expected_inbound_audio_codec.mime_type = "audio/opus";
1182   expected_inbound_audio_codec.clock_rate = 1337;
1183   expected_inbound_audio_codec.channels = 1;
1184   expected_inbound_audio_codec.sdp_fmtp_line = "minptime=10;useinbandfec=1";
1185   expected_inbound_audio_codec.transport_id = "TTransportName1";
1186 
1187   RTCCodecStats expected_outbound_audio_codec("COTTransportName1_2",
1188                                               report->timestamp_us());
1189   expected_outbound_audio_codec.payload_type = 2;
1190   expected_outbound_audio_codec.mime_type = "audio/isac";
1191   expected_outbound_audio_codec.clock_rate = 1338;
1192   expected_outbound_audio_codec.channels = 2;
1193   expected_outbound_audio_codec.transport_id = "TTransportName1";
1194 
1195   RTCCodecStats expected_inbound_video_codec(
1196       "CITTransportName1_3_level-asymmetry-allowed=1;"
1197       "packetization-mode=1;profile-level-id=42001f",
1198       report->timestamp_us());
1199   expected_inbound_video_codec.payload_type = 3;
1200   expected_inbound_video_codec.mime_type = "video/H264";
1201   expected_inbound_video_codec.clock_rate = 1339;
1202   expected_inbound_video_codec.sdp_fmtp_line =
1203       "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f";
1204   expected_inbound_video_codec.transport_id = "TTransportName1";
1205 
1206   RTCCodecStats expected_outbound_video_codec("COTTransportName1_4",
1207                                               report->timestamp_us());
1208   expected_outbound_video_codec.payload_type = 4;
1209   expected_outbound_video_codec.mime_type = "video/VP8";
1210   expected_outbound_video_codec.clock_rate = 1340;
1211   expected_outbound_video_codec.transport_id = "TTransportName1";
1212 
1213   ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
1214   EXPECT_EQ(
1215       expected_inbound_audio_codec,
1216       report->Get(expected_inbound_audio_codec.id())->cast_to<RTCCodecStats>());
1217 
1218   ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
1219   EXPECT_EQ(expected_outbound_audio_codec,
1220             report->Get(expected_outbound_audio_codec.id())
1221                 ->cast_to<RTCCodecStats>());
1222 
1223   ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
1224   EXPECT_EQ(
1225       expected_inbound_video_codec,
1226       report->Get(expected_inbound_video_codec.id())->cast_to<RTCCodecStats>());
1227 
1228   ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
1229   EXPECT_EQ(expected_outbound_video_codec,
1230             report->Get(expected_outbound_video_codec.id())
1231                 ->cast_to<RTCCodecStats>());
1232 
1233   // Now remove all the RTP streams such that there are no live codecId
1234   // references to the codecs, this should result in none of the RTCCodecStats
1235   // being exposed, despite `send_codecs` and `receive_codecs` still being set.
1236   voice_media_info.senders.clear();
1237   voice_media_info.receivers.clear();
1238   audio_channel->SetStats(voice_media_info);
1239   video_media_info.senders.clear();
1240   video_media_info.receivers.clear();
1241   video_channel->SetStats(video_media_info);
1242   stats_->stats_collector()->ClearCachedStatsReport();
1243   report = stats_->GetStatsReport();
1244   EXPECT_FALSE(report->Get(expected_inbound_audio_codec.id()));
1245   EXPECT_FALSE(report->Get(expected_outbound_audio_codec.id()));
1246   EXPECT_FALSE(report->Get(expected_inbound_video_codec.id()));
1247   EXPECT_FALSE(report->Get(expected_outbound_video_codec.id()));
1248 }
1249 
TEST_F(RTCStatsCollectorTest,CodecStatsAreCollectedPerTransport)1250 TEST_F(RTCStatsCollectorTest, CodecStatsAreCollectedPerTransport) {
1251   // PT=10
1252   RtpCodecParameters outbound_codec_pt10;
1253   outbound_codec_pt10.payload_type = 10;
1254   outbound_codec_pt10.kind = cricket::MEDIA_TYPE_VIDEO;
1255   outbound_codec_pt10.name = "VP8";
1256   outbound_codec_pt10.clock_rate = 9000;
1257 
1258   // PT=11
1259   RtpCodecParameters outbound_codec_pt11;
1260   outbound_codec_pt11.payload_type = 11;
1261   outbound_codec_pt11.kind = cricket::MEDIA_TYPE_VIDEO;
1262   outbound_codec_pt11.name = "VP8";
1263   outbound_codec_pt11.clock_rate = 9000;
1264 
1265   // Insert codecs into `send_codecs` and ensure the PTs are referenced by RTP
1266   // streams.
1267   cricket::VideoMediaInfo info_pt10;
1268   info_pt10.send_codecs.insert(
1269       std::make_pair(outbound_codec_pt10.payload_type, outbound_codec_pt10));
1270   info_pt10.senders.emplace_back();
1271   info_pt10.senders[0].add_ssrc(42);
1272   info_pt10.senders[0].codec_payload_type = outbound_codec_pt10.payload_type;
1273 
1274   cricket::VideoMediaInfo info_pt11;
1275   info_pt11.send_codecs.insert(
1276       std::make_pair(outbound_codec_pt11.payload_type, outbound_codec_pt11));
1277   info_pt11.senders.emplace_back();
1278   info_pt11.senders[0].add_ssrc(43);
1279   info_pt11.senders[0].codec_payload_type = outbound_codec_pt11.payload_type;
1280 
1281   cricket::VideoMediaInfo info_pt10_pt11;
1282   info_pt10_pt11.send_codecs.insert(
1283       std::make_pair(outbound_codec_pt10.payload_type, outbound_codec_pt10));
1284   info_pt10_pt11.send_codecs.insert(
1285       std::make_pair(outbound_codec_pt11.payload_type, outbound_codec_pt11));
1286   info_pt10_pt11.senders.emplace_back();
1287   info_pt10_pt11.senders[0].add_ssrc(44);
1288   info_pt10_pt11.senders[0].codec_payload_type =
1289       outbound_codec_pt10.payload_type;
1290   info_pt10_pt11.senders.emplace_back();
1291   info_pt10_pt11.senders[1].add_ssrc(45);
1292   info_pt10_pt11.senders[1].codec_payload_type =
1293       outbound_codec_pt11.payload_type;
1294 
1295   // First two mids contain subsets, the third one contains all PTs.
1296   pc_->AddVideoChannel("Mid1", "FirstTransport", info_pt10);
1297   pc_->AddVideoChannel("Mid2", "FirstTransport", info_pt11);
1298   pc_->AddVideoChannel("Mid3", "FirstTransport", info_pt10_pt11);
1299 
1300   // There should be no duplicate codecs because all codec references are on the
1301   // same transport.
1302   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1303   auto codec_stats = report->GetStatsOfType<RTCCodecStats>();
1304   EXPECT_EQ(codec_stats.size(), 2u);
1305 
1306   // If a second transport is added with the same PT information, this does
1307   // count as different codec objects.
1308   pc_->AddVideoChannel("Mid4", "SecondTransport", info_pt10_pt11);
1309   stats_->stats_collector()->ClearCachedStatsReport();
1310   report = stats_->GetStatsReport();
1311   codec_stats = report->GetStatsOfType<RTCCodecStats>();
1312   EXPECT_EQ(codec_stats.size(), 4u);
1313 }
1314 
TEST_F(RTCStatsCollectorTest,SamePayloadTypeButDifferentFmtpLines)1315 TEST_F(RTCStatsCollectorTest, SamePayloadTypeButDifferentFmtpLines) {
1316   // PT=111, useinbandfec=0
1317   RtpCodecParameters inbound_codec_pt111_nofec;
1318   inbound_codec_pt111_nofec.payload_type = 111;
1319   inbound_codec_pt111_nofec.kind = cricket::MEDIA_TYPE_AUDIO;
1320   inbound_codec_pt111_nofec.name = "opus";
1321   inbound_codec_pt111_nofec.clock_rate = 48000;
1322   inbound_codec_pt111_nofec.parameters.insert(
1323       std::make_pair("useinbandfec", "0"));
1324 
1325   // PT=111, useinbandfec=1
1326   RtpCodecParameters inbound_codec_pt111_fec;
1327   inbound_codec_pt111_fec.payload_type = 111;
1328   inbound_codec_pt111_fec.kind = cricket::MEDIA_TYPE_AUDIO;
1329   inbound_codec_pt111_fec.name = "opus";
1330   inbound_codec_pt111_fec.clock_rate = 48000;
1331   inbound_codec_pt111_fec.parameters.insert(
1332       std::make_pair("useinbandfec", "1"));
1333 
1334   cricket::VideoMediaInfo info_nofec;
1335   info_nofec.receive_codecs.insert(std::make_pair(
1336       inbound_codec_pt111_nofec.payload_type, inbound_codec_pt111_nofec));
1337   info_nofec.receivers.emplace_back();
1338   info_nofec.receivers[0].add_ssrc(123);
1339   info_nofec.receivers[0].codec_payload_type =
1340       inbound_codec_pt111_nofec.payload_type;
1341   cricket::VideoMediaInfo info_fec;
1342   info_fec.receive_codecs.insert(std::make_pair(
1343       inbound_codec_pt111_fec.payload_type, inbound_codec_pt111_fec));
1344   info_fec.receivers.emplace_back();
1345   info_fec.receivers[0].add_ssrc(321);
1346   info_fec.receivers[0].codec_payload_type =
1347       inbound_codec_pt111_fec.payload_type;
1348 
1349   // First two mids contain subsets, the third one contains all PTs.
1350   pc_->AddVideoChannel("Mid1", "BundledTransport", info_nofec);
1351   pc_->AddVideoChannel("Mid2", "BundledTransport", info_fec);
1352 
1353   // Despite having the same PT we should see two codec stats because their FMTP
1354   // lines are different.
1355   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1356   auto codec_stats = report->GetStatsOfType<RTCCodecStats>();
1357   EXPECT_EQ(codec_stats.size(), 2u);
1358 
1359   // Ensure SSRC uniqueness before the next AddVideoChannel() call. SSRCs need
1360   // to be unique on different m= sections when using BUNDLE.
1361   info_nofec.receivers[0].local_stats[0].ssrc = 12;
1362   info_fec.receivers[0].local_stats[0].ssrc = 21;
1363   // Adding more m= sections that does have the same FMTP lines does not result
1364   // in duplicates.
1365   pc_->AddVideoChannel("Mid3", "BundledTransport", info_nofec);
1366   pc_->AddVideoChannel("Mid4", "BundledTransport", info_fec);
1367   stats_->stats_collector()->ClearCachedStatsReport();
1368   report = stats_->GetStatsReport();
1369   codec_stats = report->GetStatsOfType<RTCCodecStats>();
1370   EXPECT_EQ(codec_stats.size(), 2u);
1371 
1372   // Same FMTP line but a different PT does count as a new codec.
1373   // PT=112, useinbandfec=1
1374   RtpCodecParameters inbound_codec_pt112_fec;
1375   inbound_codec_pt112_fec.payload_type = 112;
1376   inbound_codec_pt112_fec.kind = cricket::MEDIA_TYPE_AUDIO;
1377   inbound_codec_pt112_fec.name = "opus";
1378   inbound_codec_pt112_fec.clock_rate = 48000;
1379   inbound_codec_pt112_fec.parameters.insert(
1380       std::make_pair("useinbandfec", "1"));
1381   cricket::VideoMediaInfo info_fec_pt112;
1382   info_fec_pt112.receive_codecs.insert(std::make_pair(
1383       inbound_codec_pt112_fec.payload_type, inbound_codec_pt112_fec));
1384   info_fec_pt112.receivers.emplace_back();
1385   info_fec_pt112.receivers[0].add_ssrc(112);
1386   info_fec_pt112.receivers[0].codec_payload_type =
1387       inbound_codec_pt112_fec.payload_type;
1388   pc_->AddVideoChannel("Mid5", "BundledTransport", info_fec_pt112);
1389   stats_->stats_collector()->ClearCachedStatsReport();
1390   report = stats_->GetStatsReport();
1391   codec_stats = report->GetStatsOfType<RTCCodecStats>();
1392   EXPECT_EQ(codec_stats.size(), 3u);
1393 }
1394 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsMultiple)1395 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
1396   const char kAudioTransport[] = "audio";
1397   const char kVideoTransport[] = "video";
1398 
1399   pc_->AddVoiceChannel("audio", kAudioTransport);
1400 
1401   std::unique_ptr<CertificateInfo> audio_local_certinfo =
1402       CreateFakeCertificateAndInfoFromDers(
1403           std::vector<std::string>({"(local) audio"}));
1404   pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
1405   std::unique_ptr<CertificateInfo> audio_remote_certinfo =
1406       CreateFakeCertificateAndInfoFromDers(
1407           std::vector<std::string>({"(remote) audio"}));
1408   pc_->SetRemoteCertChain(
1409       kAudioTransport,
1410       audio_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1411 
1412   pc_->AddVideoChannel("video", kVideoTransport);
1413   std::unique_ptr<CertificateInfo> video_local_certinfo =
1414       CreateFakeCertificateAndInfoFromDers(
1415           std::vector<std::string>({"(local) video"}));
1416   pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
1417   std::unique_ptr<CertificateInfo> video_remote_certinfo =
1418       CreateFakeCertificateAndInfoFromDers(
1419           std::vector<std::string>({"(remote) video"}));
1420   pc_->SetRemoteCertChain(
1421       kVideoTransport,
1422       video_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1423 
1424   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1425   ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
1426   ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
1427   ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
1428   ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
1429 }
1430 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsChain)1431 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
1432   const char kTransportName[] = "transport";
1433 
1434   pc_->AddVoiceChannel("audio", kTransportName);
1435 
1436   std::unique_ptr<CertificateInfo> local_certinfo =
1437       CreateFakeCertificateAndInfoFromDers(
1438           {"(local) this", "(local) is", "(local) a", "(local) chain"});
1439   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
1440 
1441   std::unique_ptr<CertificateInfo> remote_certinfo =
1442       CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
1443                                             "(remote) another",
1444                                             "(remote) chain"});
1445   pc_->SetRemoteCertChain(
1446       kTransportName,
1447       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1448 
1449   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1450   ExpectReportContainsCertificateInfo(report, *local_certinfo);
1451   ExpectReportContainsCertificateInfo(report, *remote_certinfo);
1452 }
1453 
TEST_F(RTCStatsCollectorTest,CertificateStatsCache)1454 TEST_F(RTCStatsCollectorTest, CertificateStatsCache) {
1455   const char kTransportName[] = "transport";
1456   rtc::ScopedFakeClock fake_clock;
1457 
1458   pc_->AddVoiceChannel("audio", kTransportName);
1459 
1460   // Set local and remote cerificates.
1461   std::unique_ptr<CertificateInfo> initial_local_certinfo =
1462       CreateFakeCertificateAndInfoFromDers({"LocalCertA", "LocalCertB"});
1463   pc_->SetLocalCertificate(kTransportName, initial_local_certinfo->certificate);
1464   std::unique_ptr<CertificateInfo> initial_remote_certinfo =
1465       CreateFakeCertificateAndInfoFromDers({"RemoteCertA", "RemoteCertB"});
1466   pc_->SetRemoteCertChain(
1467       kTransportName,
1468       initial_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1469   ASSERT_EQ(initial_local_certinfo->fingerprints.size(), 2u);
1470   ASSERT_EQ(initial_remote_certinfo->fingerprints.size(), 2u);
1471 
1472   rtc::scoped_refptr<const RTCStatsReport> first_report =
1473       stats_->GetStatsReport();
1474   const auto* first_local_cert0 = GetCertificateStatsFromFingerprint(
1475       first_report, initial_local_certinfo->fingerprints[0]);
1476   const auto* first_local_cert1 = GetCertificateStatsFromFingerprint(
1477       first_report, initial_local_certinfo->fingerprints[1]);
1478   const auto* first_remote_cert0 = GetCertificateStatsFromFingerprint(
1479       first_report, initial_remote_certinfo->fingerprints[0]);
1480   const auto* first_remote_cert1 = GetCertificateStatsFromFingerprint(
1481       first_report, initial_remote_certinfo->fingerprints[1]);
1482   ASSERT_TRUE(first_local_cert0);
1483   ASSERT_TRUE(first_local_cert1);
1484   ASSERT_TRUE(first_remote_cert0);
1485   ASSERT_TRUE(first_remote_cert1);
1486   EXPECT_EQ(first_local_cert0->timestamp_us(), rtc::TimeMicros());
1487   EXPECT_EQ(first_local_cert1->timestamp_us(), rtc::TimeMicros());
1488   EXPECT_EQ(first_remote_cert0->timestamp_us(), rtc::TimeMicros());
1489   EXPECT_EQ(first_remote_cert1->timestamp_us(), rtc::TimeMicros());
1490 
1491   // Replace all certificates.
1492   std::unique_ptr<CertificateInfo> updated_local_certinfo =
1493       CreateFakeCertificateAndInfoFromDers(
1494           {"UpdatedLocalCertA", "UpdatedLocalCertB"});
1495   pc_->SetLocalCertificate(kTransportName, updated_local_certinfo->certificate);
1496   std::unique_ptr<CertificateInfo> updated_remote_certinfo =
1497       CreateFakeCertificateAndInfoFromDers(
1498           {"UpdatedRemoteCertA", "UpdatedRemoteCertB"});
1499   pc_->SetRemoteCertChain(
1500       kTransportName,
1501       updated_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
1502   // This test assumes fingerprints are different for the old and new
1503   // certificates.
1504   EXPECT_NE(initial_local_certinfo->fingerprints,
1505             updated_local_certinfo->fingerprints);
1506   EXPECT_NE(initial_remote_certinfo->fingerprints,
1507             updated_remote_certinfo->fingerprints);
1508 
1509   // Advance time to ensure a fresh stats report, but don't clear the
1510   // certificate stats cache.
1511   fake_clock.AdvanceTime(TimeDelta::Seconds(1));
1512   rtc::scoped_refptr<const RTCStatsReport> second_report =
1513       stats_->GetStatsReport();
1514   // We expect to see the same certificates as before due to not clearing the
1515   // certificate cache.
1516   const auto* second_local_cert0 =
1517       second_report->GetAs<RTCCertificateStats>(first_local_cert0->id());
1518   const auto* second_local_cert1 =
1519       second_report->GetAs<RTCCertificateStats>(first_local_cert1->id());
1520   const auto* second_remote_cert0 =
1521       second_report->GetAs<RTCCertificateStats>(first_remote_cert0->id());
1522   const auto* second_remote_cert1 =
1523       second_report->GetAs<RTCCertificateStats>(first_remote_cert1->id());
1524   ASSERT_TRUE(second_local_cert0);
1525   ASSERT_TRUE(second_local_cert1);
1526   ASSERT_TRUE(second_remote_cert0);
1527   ASSERT_TRUE(second_remote_cert1);
1528   // The information in the certificate stats are obsolete.
1529   EXPECT_EQ(*second_local_cert0->fingerprint,
1530             initial_local_certinfo->fingerprints[0]);
1531   EXPECT_EQ(*second_local_cert1->fingerprint,
1532             initial_local_certinfo->fingerprints[1]);
1533   EXPECT_EQ(*second_remote_cert0->fingerprint,
1534             initial_remote_certinfo->fingerprints[0]);
1535   EXPECT_EQ(*second_remote_cert1->fingerprint,
1536             initial_remote_certinfo->fingerprints[1]);
1537   // But timestamps are up-to-date, because this is a fresh stats report.
1538   EXPECT_EQ(second_local_cert0->timestamp_us(), rtc::TimeMicros());
1539   EXPECT_EQ(second_local_cert1->timestamp_us(), rtc::TimeMicros());
1540   EXPECT_EQ(second_remote_cert0->timestamp_us(), rtc::TimeMicros());
1541   EXPECT_EQ(second_remote_cert1->timestamp_us(), rtc::TimeMicros());
1542   // The updated certificates are not part of the report yet.
1543   EXPECT_FALSE(GetCertificateStatsFromFingerprint(
1544       second_report, updated_local_certinfo->fingerprints[0]));
1545   EXPECT_FALSE(GetCertificateStatsFromFingerprint(
1546       second_report, updated_local_certinfo->fingerprints[1]));
1547   EXPECT_FALSE(GetCertificateStatsFromFingerprint(
1548       second_report, updated_remote_certinfo->fingerprints[0]));
1549   EXPECT_FALSE(GetCertificateStatsFromFingerprint(
1550       second_report, updated_remote_certinfo->fingerprints[1]));
1551 
1552   // Clear the cache, including the cached certificates.
1553   stats_->stats_collector()->ClearCachedStatsReport();
1554   rtc::scoped_refptr<const RTCStatsReport> third_report =
1555       stats_->GetStatsReport();
1556   // Now the old certificates stats should be deleted.
1557   EXPECT_FALSE(third_report->Get(first_local_cert0->id()));
1558   EXPECT_FALSE(third_report->Get(first_local_cert1->id()));
1559   EXPECT_FALSE(third_report->Get(first_remote_cert0->id()));
1560   EXPECT_FALSE(third_report->Get(first_remote_cert1->id()));
1561   // And updated certificates exist.
1562   EXPECT_TRUE(GetCertificateStatsFromFingerprint(
1563       third_report, updated_local_certinfo->fingerprints[0]));
1564   EXPECT_TRUE(GetCertificateStatsFromFingerprint(
1565       third_report, updated_local_certinfo->fingerprints[1]));
1566   EXPECT_TRUE(GetCertificateStatsFromFingerprint(
1567       third_report, updated_remote_certinfo->fingerprints[0]));
1568   EXPECT_TRUE(GetCertificateStatsFromFingerprint(
1569       third_report, updated_remote_certinfo->fingerprints[1]));
1570 }
1571 
TEST_F(RTCStatsCollectorTest,CollectTwoRTCDataChannelStatsWithPendingId)1572 TEST_F(RTCStatsCollectorTest, CollectTwoRTCDataChannelStatsWithPendingId) {
1573   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1574       /*id=*/-1, DataChannelInterface::kConnecting));
1575   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1576       /*id=*/-1, DataChannelInterface::kConnecting));
1577 
1578   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1579 }
1580 
TEST_F(RTCStatsCollectorTest,CollectRTCDataChannelStats)1581 TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
1582   // Note: The test assumes data channel IDs are predictable.
1583   // This is not a safe assumption, but in order to make it work for
1584   // the test, we reset the ID allocator at test start.
1585   SctpDataChannel::ResetInternalIdAllocatorForTesting(-1);
1586   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1587       0, "MockSctpDataChannel0", DataChannelInterface::kConnecting, "udp", 1, 2,
1588       3, 4));
1589   RTCDataChannelStats expected_data_channel0("D0", 0);
1590   expected_data_channel0.label = "MockSctpDataChannel0";
1591   expected_data_channel0.protocol = "udp";
1592   expected_data_channel0.data_channel_identifier = 0;
1593   expected_data_channel0.state = "connecting";
1594   expected_data_channel0.messages_sent = 1;
1595   expected_data_channel0.bytes_sent = 2;
1596   expected_data_channel0.messages_received = 3;
1597   expected_data_channel0.bytes_received = 4;
1598 
1599   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1600       1, "MockSctpDataChannel1", DataChannelInterface::kOpen, "tcp", 5, 6, 7,
1601       8));
1602   RTCDataChannelStats expected_data_channel1("D1", 0);
1603   expected_data_channel1.label = "MockSctpDataChannel1";
1604   expected_data_channel1.protocol = "tcp";
1605   expected_data_channel1.data_channel_identifier = 1;
1606   expected_data_channel1.state = "open";
1607   expected_data_channel1.messages_sent = 5;
1608   expected_data_channel1.bytes_sent = 6;
1609   expected_data_channel1.messages_received = 7;
1610   expected_data_channel1.bytes_received = 8;
1611 
1612   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1613       2, "MockSctpDataChannel2", DataChannelInterface::kClosing, "udp", 9, 10,
1614       11, 12));
1615   RTCDataChannelStats expected_data_channel2("D2", 0);
1616   expected_data_channel2.label = "MockSctpDataChannel2";
1617   expected_data_channel2.protocol = "udp";
1618   expected_data_channel2.data_channel_identifier = 2;
1619   expected_data_channel2.state = "closing";
1620   expected_data_channel2.messages_sent = 9;
1621   expected_data_channel2.bytes_sent = 10;
1622   expected_data_channel2.messages_received = 11;
1623   expected_data_channel2.bytes_received = 12;
1624 
1625   pc_->AddSctpDataChannel(rtc::make_ref_counted<MockSctpDataChannel>(
1626       3, "MockSctpDataChannel3", DataChannelInterface::kClosed, "tcp", 13, 14,
1627       15, 16));
1628   RTCDataChannelStats expected_data_channel3("D3", 0);
1629   expected_data_channel3.label = "MockSctpDataChannel3";
1630   expected_data_channel3.protocol = "tcp";
1631   expected_data_channel3.data_channel_identifier = 3;
1632   expected_data_channel3.state = "closed";
1633   expected_data_channel3.messages_sent = 13;
1634   expected_data_channel3.bytes_sent = 14;
1635   expected_data_channel3.messages_received = 15;
1636   expected_data_channel3.bytes_received = 16;
1637 
1638   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1639 
1640   ASSERT_TRUE(report->Get(expected_data_channel0.id()));
1641   EXPECT_EQ(
1642       expected_data_channel0,
1643       report->Get(expected_data_channel0.id())->cast_to<RTCDataChannelStats>());
1644   ASSERT_TRUE(report->Get(expected_data_channel1.id()));
1645   EXPECT_EQ(
1646       expected_data_channel1,
1647       report->Get(expected_data_channel1.id())->cast_to<RTCDataChannelStats>());
1648   ASSERT_TRUE(report->Get(expected_data_channel2.id()));
1649   EXPECT_EQ(
1650       expected_data_channel2,
1651       report->Get(expected_data_channel2.id())->cast_to<RTCDataChannelStats>());
1652   ASSERT_TRUE(report->Get(expected_data_channel3.id()));
1653   EXPECT_EQ(
1654       expected_data_channel3,
1655       report->Get(expected_data_channel3.id())->cast_to<RTCDataChannelStats>());
1656 }
1657 
TEST_F(RTCStatsCollectorTest,CollectRTCIceCandidateStats)1658 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
1659   // Candidates in the first transport stats.
1660   std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
1661       "1.2.3.4", 5, "a_local_host's protocol", rtc::ADAPTER_TYPE_VPN,
1662       cricket::LOCAL_PORT_TYPE, 0, rtc::ADAPTER_TYPE_ETHERNET);
1663   RTCLocalIceCandidateStats expected_a_local_host("I" + a_local_host->id(), 0);
1664   expected_a_local_host.transport_id = "Ta0";
1665   expected_a_local_host.network_type = "vpn";
1666   expected_a_local_host.ip = "1.2.3.4";
1667   expected_a_local_host.address = "1.2.3.4";
1668   expected_a_local_host.port = 5;
1669   expected_a_local_host.protocol = "a_local_host's protocol";
1670   expected_a_local_host.candidate_type = "host";
1671   expected_a_local_host.priority = 0;
1672   expected_a_local_host.vpn = true;
1673   expected_a_local_host.network_adapter_type = RTCNetworkAdapterType::kEthernet;
1674   expected_a_local_host.foundation = "foundationIsAString";
1675   expected_a_local_host.username_fragment = "iceusernamefragment";
1676 
1677   std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
1678       "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1679       cricket::STUN_PORT_TYPE, 1);
1680   RTCRemoteIceCandidateStats expected_a_remote_srflx("I" + a_remote_srflx->id(),
1681                                                      0);
1682   expected_a_remote_srflx.transport_id = "Ta0";
1683   expected_a_remote_srflx.ip = "6.7.8.9";
1684   expected_a_remote_srflx.address = "6.7.8.9";
1685   expected_a_remote_srflx.port = 10;
1686   expected_a_remote_srflx.protocol = "remote_srflx's protocol";
1687   expected_a_remote_srflx.candidate_type = "srflx";
1688   expected_a_remote_srflx.priority = 1;
1689   expected_a_remote_srflx.foundation = "foundationIsAString";
1690   expected_a_remote_srflx.username_fragment = "iceusernamefragment";
1691 
1692   std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
1693       "11.12.13.14", 15, "a_local_prflx's protocol",
1694       rtc::ADAPTER_TYPE_CELLULAR_2G, cricket::PRFLX_PORT_TYPE, 2);
1695   RTCLocalIceCandidateStats expected_a_local_prflx("I" + a_local_prflx->id(),
1696                                                    0);
1697   expected_a_local_prflx.transport_id = "Ta0";
1698   expected_a_local_prflx.network_type = "cellular";
1699   expected_a_local_prflx.ip = "11.12.13.14";
1700   expected_a_local_prflx.address = "11.12.13.14";
1701   expected_a_local_prflx.port = 15;
1702   expected_a_local_prflx.protocol = "a_local_prflx's protocol";
1703   expected_a_local_prflx.candidate_type = "prflx";
1704   expected_a_local_prflx.priority = 2;
1705   expected_a_local_prflx.vpn = false;
1706   expected_a_local_prflx.network_adapter_type =
1707       RTCNetworkAdapterType::kCellular2g;
1708   expected_a_local_prflx.foundation = "foundationIsAString";
1709   expected_a_local_prflx.username_fragment = "iceusernamefragment";
1710 
1711   std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
1712       "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1713       cricket::RELAY_PORT_TYPE, 3);
1714   RTCRemoteIceCandidateStats expected_a_remote_relay("I" + a_remote_relay->id(),
1715                                                      0);
1716   expected_a_remote_relay.transport_id = "Ta0";
1717   expected_a_remote_relay.ip = "16.17.18.19";
1718   expected_a_remote_relay.address = "16.17.18.19";
1719   expected_a_remote_relay.port = 20;
1720   expected_a_remote_relay.protocol = "a_remote_relay's protocol";
1721   expected_a_remote_relay.candidate_type = "relay";
1722   expected_a_remote_relay.priority = 3;
1723   expected_a_remote_relay.foundation = "foundationIsAString";
1724   expected_a_remote_relay.username_fragment = "iceusernamefragment";
1725 
1726   std::unique_ptr<cricket::Candidate> a_local_relay = CreateFakeCandidate(
1727       "16.17.18.19", 21, "a_local_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1728       cricket::RELAY_PORT_TYPE, 1);
1729   a_local_relay->set_relay_protocol("tcp");
1730   a_local_relay->set_url("turn:url1");
1731 
1732   RTCLocalIceCandidateStats expected_a_local_relay("I" + a_local_relay->id(),
1733                                                    0);
1734   expected_a_local_relay.transport_id = "Ta0";
1735   expected_a_local_relay.network_type = "unknown";
1736   expected_a_local_relay.ip = "16.17.18.19";
1737   expected_a_local_relay.address = "16.17.18.19";
1738   expected_a_local_relay.port = 21;
1739   expected_a_local_relay.protocol = "a_local_relay's protocol";
1740   expected_a_local_relay.relay_protocol = "tcp";
1741   expected_a_local_relay.candidate_type = "relay";
1742   expected_a_local_relay.priority = 1;
1743   expected_a_local_relay.url = "turn:url1";
1744   expected_a_local_relay.vpn = false;
1745   expected_a_local_relay.network_adapter_type = RTCNetworkAdapterType::kUnknown;
1746   expected_a_local_relay.foundation = "foundationIsAString";
1747   expected_a_local_relay.username_fragment = "iceusernamefragment";
1748 
1749   std::unique_ptr<cricket::Candidate> a_local_relay_prflx = CreateFakeCandidate(
1750       "11.12.13.20", 22, "a_local_relay_prflx's protocol",
1751       rtc::ADAPTER_TYPE_UNKNOWN, cricket::PRFLX_PORT_TYPE, 1);
1752   a_local_relay_prflx->set_relay_protocol("udp");
1753 
1754   RTCLocalIceCandidateStats expected_a_local_relay_prflx(
1755       "I" + a_local_relay_prflx->id(), 0);
1756   expected_a_local_relay_prflx.transport_id = "Ta0";
1757   expected_a_local_relay_prflx.network_type = "unknown";
1758   expected_a_local_relay_prflx.ip = "11.12.13.20";
1759   expected_a_local_relay_prflx.address = "11.12.13.20";
1760   expected_a_local_relay_prflx.port = 22;
1761   expected_a_local_relay_prflx.protocol = "a_local_relay_prflx's protocol";
1762   expected_a_local_relay_prflx.relay_protocol = "udp";
1763   expected_a_local_relay_prflx.candidate_type = "prflx";
1764   expected_a_local_relay_prflx.priority = 1;
1765   expected_a_local_relay_prflx.vpn = false;
1766   expected_a_local_relay_prflx.network_adapter_type =
1767       RTCNetworkAdapterType::kUnknown;
1768   expected_a_local_relay_prflx.foundation = "foundationIsAString";
1769   expected_a_local_relay_prflx.username_fragment = "iceusernamefragment";
1770 
1771   // A non-paired local candidate.
1772   std::unique_ptr<cricket::Candidate> a_local_host_not_paired =
1773       CreateFakeCandidate("1.2.3.4", 4404, "a_local_host_not_paired's protocol",
1774                           rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0,
1775                           rtc::ADAPTER_TYPE_ETHERNET);
1776   RTCLocalIceCandidateStats expected_a_local_host_not_paired(
1777       "I" + a_local_host_not_paired->id(), 0);
1778   expected_a_local_host_not_paired.transport_id = "Ta0";
1779   expected_a_local_host_not_paired.network_type = "vpn";
1780   expected_a_local_host_not_paired.ip = "1.2.3.4";
1781   expected_a_local_host_not_paired.address = "1.2.3.4";
1782   expected_a_local_host_not_paired.port = 4404;
1783   expected_a_local_host_not_paired.protocol =
1784       "a_local_host_not_paired's protocol";
1785   expected_a_local_host_not_paired.candidate_type = "host";
1786   expected_a_local_host_not_paired.priority = 0;
1787   expected_a_local_host_not_paired.vpn = true;
1788   expected_a_local_host_not_paired.network_adapter_type =
1789       RTCNetworkAdapterType::kEthernet;
1790   expected_a_local_host_not_paired.foundation = "foundationIsAString";
1791   expected_a_local_host_not_paired.username_fragment = "iceusernamefragment";
1792 
1793   // Candidates in the second transport stats.
1794   std::unique_ptr<cricket::Candidate> b_local =
1795       CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
1796                           rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
1797   RTCLocalIceCandidateStats expected_b_local("I" + b_local->id(), 0);
1798   expected_b_local.transport_id = "Tb0";
1799   expected_b_local.network_type = "wifi";
1800   expected_b_local.ip = "42.42.42.42";
1801   expected_b_local.address = "42.42.42.42";
1802   expected_b_local.port = 42;
1803   expected_b_local.protocol = "b_local's protocol";
1804   expected_b_local.candidate_type = "host";
1805   expected_b_local.priority = 42;
1806   expected_b_local.vpn = false;
1807   expected_b_local.network_adapter_type = RTCNetworkAdapterType::kWifi;
1808   expected_b_local.foundation = "foundationIsAString";
1809   expected_b_local.username_fragment = "iceusernamefragment";
1810 
1811   std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
1812       "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1813       cricket::LOCAL_PORT_TYPE, 42);
1814   RTCRemoteIceCandidateStats expected_b_remote("I" + b_remote->id(), 0);
1815   expected_b_remote.transport_id = "Tb0";
1816   expected_b_remote.ip = "42.42.42.42";
1817   expected_b_remote.address = "42.42.42.42";
1818   expected_b_remote.port = 42;
1819   expected_b_remote.protocol = "b_remote's protocol";
1820   expected_b_remote.candidate_type = "host";
1821   expected_b_remote.priority = 42;
1822   expected_b_remote.foundation = "foundationIsAString";
1823   expected_b_remote.username_fragment = "iceusernamefragment";
1824 
1825   // Add candidate pairs to connection.
1826   cricket::TransportChannelStats a_transport_channel_stats;
1827   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1828       cricket::ConnectionInfo());
1829   a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1830       .local_candidate = *a_local_host.get();
1831   a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1832       .remote_candidate = *a_remote_srflx.get();
1833   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1834       cricket::ConnectionInfo());
1835   a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1836       .local_candidate = *a_local_prflx.get();
1837   a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1838       .remote_candidate = *a_remote_relay.get();
1839   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1840       cricket::ConnectionInfo());
1841   a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1842       .local_candidate = *a_local_relay.get();
1843   a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1844       .remote_candidate = *a_remote_relay.get();
1845   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1846       cricket::ConnectionInfo());
1847   a_transport_channel_stats.ice_transport_stats.connection_infos[3]
1848       .local_candidate = *a_local_relay_prflx.get();
1849   a_transport_channel_stats.ice_transport_stats.connection_infos[3]
1850       .remote_candidate = *a_remote_relay.get();
1851   a_transport_channel_stats.ice_transport_stats.candidate_stats_list.push_back(
1852       cricket::CandidateStats(*a_local_host_not_paired.get()));
1853 
1854   pc_->AddVoiceChannel("audio", "a");
1855   pc_->SetTransportStats("a", a_transport_channel_stats);
1856 
1857   cricket::TransportChannelStats b_transport_channel_stats;
1858   b_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1859       cricket::ConnectionInfo());
1860   b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1861       .local_candidate = *b_local.get();
1862   b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1863       .remote_candidate = *b_remote.get();
1864 
1865   pc_->AddVideoChannel("video", "b");
1866   pc_->SetTransportStats("b", b_transport_channel_stats);
1867 
1868   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1869 
1870   ASSERT_TRUE(report->Get(expected_a_local_host.id()));
1871   EXPECT_EQ(expected_a_local_host, report->Get(expected_a_local_host.id())
1872                                        ->cast_to<RTCLocalIceCandidateStats>());
1873 
1874   ASSERT_TRUE(report->Get(expected_a_local_host_not_paired.id()));
1875   EXPECT_EQ(expected_a_local_host_not_paired,
1876             report->Get(expected_a_local_host_not_paired.id())
1877                 ->cast_to<RTCLocalIceCandidateStats>());
1878 
1879   ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
1880   EXPECT_EQ(expected_a_remote_srflx,
1881             report->Get(expected_a_remote_srflx.id())
1882                 ->cast_to<RTCRemoteIceCandidateStats>());
1883   ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
1884   EXPECT_EQ(expected_a_local_prflx, report->Get(expected_a_local_prflx.id())
1885                                         ->cast_to<RTCLocalIceCandidateStats>());
1886   ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
1887   EXPECT_EQ(expected_a_remote_relay,
1888             report->Get(expected_a_remote_relay.id())
1889                 ->cast_to<RTCRemoteIceCandidateStats>());
1890   ASSERT_TRUE(report->Get(expected_a_local_relay.id()));
1891   EXPECT_EQ(expected_a_local_relay, report->Get(expected_a_local_relay.id())
1892                                         ->cast_to<RTCLocalIceCandidateStats>());
1893   ASSERT_TRUE(report->Get(expected_a_local_relay_prflx.id()));
1894   EXPECT_EQ(expected_a_local_relay_prflx,
1895             report->Get(expected_a_local_relay_prflx.id())
1896                 ->cast_to<RTCLocalIceCandidateStats>());
1897   ASSERT_TRUE(report->Get(expected_b_local.id()));
1898   EXPECT_EQ(
1899       expected_b_local,
1900       report->Get(expected_b_local.id())->cast_to<RTCLocalIceCandidateStats>());
1901   ASSERT_TRUE(report->Get(expected_b_remote.id()));
1902   EXPECT_EQ(expected_b_remote, report->Get(expected_b_remote.id())
1903                                    ->cast_to<RTCRemoteIceCandidateStats>());
1904   EXPECT_TRUE(report->Get("Ta0"));
1905   EXPECT_TRUE(report->Get("Tb0"));
1906 }
1907 
TEST_F(RTCStatsCollectorTest,CollectRTCIceCandidatePairStats)1908 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
1909   const char kTransportName[] = "transport";
1910 
1911   std::unique_ptr<cricket::Candidate> local_candidate =
1912       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1913                           cricket::LOCAL_PORT_TYPE, 42);
1914   local_candidate->set_username("local_iceusernamefragment");
1915 
1916   std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
1917       "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1918       cricket::STUN_PORT_TYPE, 42);
1919   remote_candidate->set_related_address(rtc::SocketAddress("192.168.2.1", 43));
1920   remote_candidate->set_username("remote_iceusernamefragment");
1921 
1922   cricket::ConnectionInfo connection_info;
1923   connection_info.best_connection = false;
1924   connection_info.local_candidate = *local_candidate.get();
1925   connection_info.remote_candidate = *remote_candidate.get();
1926   connection_info.writable = true;
1927   connection_info.sent_discarded_packets = 3;
1928   connection_info.sent_total_packets = 10;
1929   connection_info.packets_received = 51;
1930   connection_info.sent_discarded_bytes = 7;
1931   connection_info.sent_total_bytes = 42;
1932   connection_info.recv_total_bytes = 1234;
1933   connection_info.total_round_trip_time_ms = 0;
1934   connection_info.current_round_trip_time_ms = absl::nullopt;
1935   connection_info.recv_ping_requests = 2020;
1936   connection_info.sent_ping_requests_total = 2222;
1937   connection_info.sent_ping_requests_before_first_response = 2000;
1938   connection_info.recv_ping_responses = 4321;
1939   connection_info.sent_ping_responses = 1000;
1940   connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
1941   connection_info.priority = 5555;
1942   connection_info.nominated = false;
1943   connection_info.last_data_received = Timestamp::Millis(2500);
1944   connection_info.last_data_sent = Timestamp::Millis(5200);
1945 
1946   cricket::TransportChannelStats transport_channel_stats;
1947   transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1948   transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1949       connection_info);
1950 
1951   pc_->AddVideoChannel("video", kTransportName);
1952   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1953 
1954   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1955 
1956   RTCIceCandidatePairStats expected_pair(
1957       "CP" + local_candidate->id() + "_" + remote_candidate->id(),
1958       report->timestamp_us());
1959   expected_pair.transport_id =
1960       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1961   expected_pair.local_candidate_id = "I" + local_candidate->id();
1962   expected_pair.remote_candidate_id = "I" + remote_candidate->id();
1963   expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1964   expected_pair.priority = 5555;
1965   expected_pair.nominated = false;
1966   expected_pair.writable = true;
1967   expected_pair.packets_sent = 7;
1968   expected_pair.packets_received = 51;
1969   expected_pair.packets_discarded_on_send = 3;
1970   expected_pair.bytes_sent = 42;
1971   expected_pair.bytes_received = 1234;
1972   expected_pair.bytes_discarded_on_send = 7;
1973   expected_pair.total_round_trip_time = 0.0;
1974   expected_pair.requests_received = 2020;
1975   expected_pair.requests_sent = 2222;
1976   expected_pair.responses_received = 4321;
1977   expected_pair.responses_sent = 1000;
1978   expected_pair.consent_requests_sent = (2222 - 2000);
1979   expected_pair.last_packet_received_timestamp = 2500;
1980   expected_pair.last_packet_sent_timestamp = 5200;
1981 
1982   // `expected_pair.current_round_trip_time` should be undefined because the
1983   // current RTT is not set.
1984   // `expected_pair.available_[outgoing/incoming]_bitrate` should be undefined
1985   // because is is not the current pair.
1986 
1987   ASSERT_TRUE(report->Get(expected_pair.id()));
1988   EXPECT_EQ(
1989       expected_pair,
1990       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1991   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1992 
1993   // Set nominated and "GetStats" again.
1994   transport_channel_stats.ice_transport_stats.connection_infos[0].nominated =
1995       true;
1996   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1997   report = stats_->GetFreshStatsReport();
1998   expected_pair.nominated = true;
1999   ASSERT_TRUE(report->Get(expected_pair.id()));
2000   EXPECT_EQ(
2001       expected_pair,
2002       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
2003   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
2004 
2005   // Set round trip times and "GetStats" again.
2006   transport_channel_stats.ice_transport_stats.connection_infos[0]
2007       .total_round_trip_time_ms = 7331;
2008   transport_channel_stats.ice_transport_stats.connection_infos[0]
2009       .current_round_trip_time_ms = 1337;
2010   pc_->SetTransportStats(kTransportName, transport_channel_stats);
2011   report = stats_->GetFreshStatsReport();
2012   expected_pair.total_round_trip_time = 7.331;
2013   expected_pair.current_round_trip_time = 1.337;
2014   ASSERT_TRUE(report->Get(expected_pair.id()));
2015   EXPECT_EQ(
2016       expected_pair,
2017       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
2018   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
2019 
2020   // Make pair the current pair, clear bandwidth and "GetStats" again.
2021   transport_channel_stats.ice_transport_stats.connection_infos[0]
2022       .best_connection = true;
2023   pc_->SetTransportStats(kTransportName, transport_channel_stats);
2024   report = stats_->GetFreshStatsReport();
2025   // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
2026   // undefined because bandwidth is not set.
2027   ASSERT_TRUE(report->Get(expected_pair.id()));
2028   EXPECT_EQ(
2029       expected_pair,
2030       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
2031   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
2032 
2033   // Set bandwidth and "GetStats" again.
2034   webrtc::Call::Stats call_stats;
2035   const int kSendBandwidth = 888;
2036   call_stats.send_bandwidth_bps = kSendBandwidth;
2037   const int kRecvBandwidth = 999;
2038   call_stats.recv_bandwidth_bps = kRecvBandwidth;
2039   pc_->SetCallStats(call_stats);
2040   report = stats_->GetFreshStatsReport();
2041   expected_pair.available_outgoing_bitrate = kSendBandwidth;
2042   expected_pair.available_incoming_bitrate = kRecvBandwidth;
2043   ASSERT_TRUE(report->Get(expected_pair.id()));
2044   EXPECT_EQ(
2045       expected_pair,
2046       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
2047   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
2048 
2049   RTCLocalIceCandidateStats expected_local_candidate(
2050       *expected_pair.local_candidate_id, report->timestamp_us());
2051   expected_local_candidate.transport_id = *expected_pair.transport_id;
2052   expected_local_candidate.network_type = "wifi";
2053   expected_local_candidate.ip = "42.42.42.42";
2054   expected_local_candidate.address = "42.42.42.42";
2055   expected_local_candidate.port = 42;
2056   expected_local_candidate.protocol = "protocol";
2057   expected_local_candidate.candidate_type = "host";
2058   expected_local_candidate.priority = 42;
2059   expected_local_candidate.foundation = "foundationIsAString";
2060   expected_local_candidate.username_fragment = "local_iceusernamefragment";
2061   expected_local_candidate.vpn = false;
2062   expected_local_candidate.network_adapter_type = RTCNetworkAdapterType::kWifi;
2063   ASSERT_TRUE(report->Get(expected_local_candidate.id()));
2064   EXPECT_EQ(expected_local_candidate,
2065             report->Get(expected_local_candidate.id())
2066                 ->cast_to<RTCLocalIceCandidateStats>());
2067 
2068   RTCRemoteIceCandidateStats expected_remote_candidate(
2069       *expected_pair.remote_candidate_id, report->timestamp_us());
2070   expected_remote_candidate.transport_id = *expected_pair.transport_id;
2071   expected_remote_candidate.ip = "42.42.42.42";
2072   expected_remote_candidate.address = "42.42.42.42";
2073   expected_remote_candidate.port = 42;
2074   expected_remote_candidate.protocol = "protocol";
2075   expected_remote_candidate.candidate_type = "srflx";
2076   expected_remote_candidate.priority = 42;
2077   expected_remote_candidate.foundation = "foundationIsAString";
2078   expected_remote_candidate.username_fragment = "remote_iceusernamefragment";
2079   expected_remote_candidate.related_address = "192.168.2.1";
2080   expected_remote_candidate.related_port = 43;
2081   ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
2082   EXPECT_EQ(expected_remote_candidate,
2083             report->Get(expected_remote_candidate.id())
2084                 ->cast_to<RTCRemoteIceCandidateStats>());
2085 }
2086 
TEST_F(RTCStatsCollectorTest,CollectRTCPeerConnectionStats)2087 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
2088   {
2089     rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2090     RTCPeerConnectionStats expected("P", report->timestamp_us());
2091     expected.data_channels_opened = 0;
2092     expected.data_channels_closed = 0;
2093     ASSERT_TRUE(report->Get("P"));
2094     EXPECT_EQ(expected, report->Get("P")->cast_to<RTCPeerConnectionStats>());
2095   }
2096 
2097   // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
2098   FakeDataChannelController controller;
2099   rtc::scoped_refptr<SctpDataChannel> dummy_channel_a = SctpDataChannel::Create(
2100       &controller, "DummyChannelA", InternalDataChannelInit(),
2101       rtc::Thread::Current(), rtc::Thread::Current());
2102   pc_->SignalSctpDataChannelCreated()(dummy_channel_a.get());
2103   rtc::scoped_refptr<SctpDataChannel> dummy_channel_b = SctpDataChannel::Create(
2104       &controller, "DummyChannelB", InternalDataChannelInit(),
2105       rtc::Thread::Current(), rtc::Thread::Current());
2106   pc_->SignalSctpDataChannelCreated()(dummy_channel_b.get());
2107 
2108   dummy_channel_a->SignalOpened(dummy_channel_a.get());
2109   // Closing a channel that is not opened should not affect the counts.
2110   dummy_channel_b->SignalClosed(dummy_channel_b.get());
2111 
2112   {
2113     rtc::scoped_refptr<const RTCStatsReport> report =
2114         stats_->GetFreshStatsReport();
2115     RTCPeerConnectionStats expected("P", report->timestamp_us());
2116     expected.data_channels_opened = 1;
2117     expected.data_channels_closed = 0;
2118     ASSERT_TRUE(report->Get("P"));
2119     EXPECT_EQ(expected, report->Get("P")->cast_to<RTCPeerConnectionStats>());
2120   }
2121 
2122   dummy_channel_b->SignalOpened(dummy_channel_b.get());
2123   dummy_channel_b->SignalClosed(dummy_channel_b.get());
2124 
2125   {
2126     rtc::scoped_refptr<const RTCStatsReport> report =
2127         stats_->GetFreshStatsReport();
2128     RTCPeerConnectionStats expected("P", report->timestamp_us());
2129     expected.data_channels_opened = 2;
2130     expected.data_channels_closed = 1;
2131     ASSERT_TRUE(report->Get("P"));
2132     EXPECT_EQ(expected, report->Get("P")->cast_to<RTCPeerConnectionStats>());
2133   }
2134 
2135   // Re-opening a data channel (or opening a new data channel that is re-using
2136   // the same address in memory) should increase the opened count.
2137   dummy_channel_b->SignalOpened(dummy_channel_b.get());
2138 
2139   {
2140     rtc::scoped_refptr<const RTCStatsReport> report =
2141         stats_->GetFreshStatsReport();
2142     RTCPeerConnectionStats expected("P", report->timestamp_us());
2143     expected.data_channels_opened = 3;
2144     expected.data_channels_closed = 1;
2145     ASSERT_TRUE(report->Get("P"));
2146     EXPECT_EQ(expected, report->Get("P")->cast_to<RTCPeerConnectionStats>());
2147   }
2148 
2149   dummy_channel_a->SignalClosed(dummy_channel_a.get());
2150   dummy_channel_b->SignalClosed(dummy_channel_b.get());
2151 
2152   {
2153     rtc::scoped_refptr<const RTCStatsReport> report =
2154         stats_->GetFreshStatsReport();
2155     RTCPeerConnectionStats expected("P", report->timestamp_us());
2156     expected.data_channels_opened = 3;
2157     expected.data_channels_closed = 3;
2158     ASSERT_TRUE(report->Get("P"));
2159     EXPECT_EQ(expected, report->Get("P")->cast_to<RTCPeerConnectionStats>());
2160   }
2161 }
2162 
TEST_F(RTCStatsCollectorTest,CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio)2163 TEST_F(RTCStatsCollectorTest,
2164        CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
2165   rtc::scoped_refptr<MediaStream> local_stream =
2166       MediaStream::Create("LocalStreamId");
2167   pc_->mutable_local_streams()->AddStream(local_stream);
2168 
2169   // Local audio track
2170   rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
2171       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
2172                       MediaStreamTrackInterface::kEnded);
2173   local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
2174       static_cast<AudioTrackInterface*>(local_audio_track.get())));
2175 
2176   cricket::VoiceSenderInfo voice_sender_info_ssrc1;
2177   voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
2178   voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
2179   voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
2180   voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
2181 
2182   stats_->CreateMockRtpSendersReceiversAndChannels(
2183       {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
2184       {}, {}, {local_stream->id()}, {});
2185 
2186   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2187 
2188   DEPRECATED_RTCMediaStreamStats expected_local_stream(
2189       IdForType<DEPRECATED_RTCMediaStreamStats>(report.get()),
2190       report->timestamp_us());
2191   expected_local_stream.stream_identifier = local_stream->id();
2192   expected_local_stream.track_ids = {
2193       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get())};
2194   ASSERT_TRUE(report->Get(expected_local_stream.id()))
2195       << "Did not find " << expected_local_stream.id() << " in "
2196       << report->ToJson();
2197   EXPECT_EQ(expected_local_stream,
2198             report->Get(expected_local_stream.id())
2199                 ->cast_to<DEPRECATED_RTCMediaStreamStats>());
2200 
2201   DEPRECATED_RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
2202       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get()),
2203       report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
2204   expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
2205   expected_local_audio_track_ssrc1.media_source_id =
2206       "SA11";  // Attachment ID = SSRC + 10
2207   expected_local_audio_track_ssrc1.remote_source = false;
2208   expected_local_audio_track_ssrc1.ended = true;
2209   expected_local_audio_track_ssrc1.detached = false;
2210   expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
2211   expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
2212   ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
2213       << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
2214       << report->ToJson();
2215   EXPECT_EQ(expected_local_audio_track_ssrc1,
2216             report->Get(expected_local_audio_track_ssrc1.id())
2217                 ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>());
2218 }
2219 
TEST_F(RTCStatsCollectorTest,CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio)2220 TEST_F(RTCStatsCollectorTest,
2221        CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
2222   rtc::scoped_refptr<MediaStream> remote_stream =
2223       MediaStream::Create("RemoteStreamId");
2224   pc_->mutable_remote_streams()->AddStream(remote_stream);
2225 
2226   // Remote audio track
2227   rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
2228       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
2229                       MediaStreamTrackInterface::kLive);
2230   remote_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
2231       static_cast<AudioTrackInterface*>(remote_audio_track.get())));
2232 
2233   cricket::VoiceReceiverInfo voice_receiver_info;
2234   voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
2235   voice_receiver_info.local_stats[0].ssrc = 3;
2236   voice_receiver_info.audio_level = 16383;  // [0,32767]
2237   voice_receiver_info.total_output_energy = 0.125;
2238   voice_receiver_info.total_samples_received = 4567;
2239   voice_receiver_info.total_output_duration = 0.25;
2240   voice_receiver_info.concealed_samples = 123;
2241   voice_receiver_info.concealment_events = 12;
2242   voice_receiver_info.inserted_samples_for_deceleration = 987;
2243   voice_receiver_info.removed_samples_for_acceleration = 876;
2244   voice_receiver_info.silent_concealed_samples = 765;
2245   voice_receiver_info.jitter_buffer_delay_seconds = 3.456;
2246   voice_receiver_info.jitter_buffer_emitted_count = 13;
2247 
2248   stats_->CreateMockRtpSendersReceiversAndChannels(
2249       {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
2250       {}, {}, {remote_stream});
2251 
2252   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2253 
2254   DEPRECATED_RTCMediaStreamStats expected_remote_stream(
2255       IdForType<DEPRECATED_RTCMediaStreamStats>(report.get()),
2256       report->timestamp_us());
2257   expected_remote_stream.stream_identifier = remote_stream->id();
2258   expected_remote_stream.track_ids = std::vector<std::string>(
2259       {IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get())});
2260   ASSERT_TRUE(report->Get(expected_remote_stream.id()))
2261       << "Did not find " << expected_remote_stream.id() << " in "
2262       << report->ToJson();
2263   EXPECT_EQ(expected_remote_stream,
2264             report->Get(expected_remote_stream.id())
2265                 ->cast_to<DEPRECATED_RTCMediaStreamStats>());
2266 
2267   DEPRECATED_RTCMediaStreamTrackStats expected_remote_audio_track(
2268       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get()),
2269       report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
2270   expected_remote_audio_track.track_identifier = remote_audio_track->id();
2271   // `expected_remote_audio_track.media_source_id` should be undefined
2272   // because the track is remote.
2273   expected_remote_audio_track.remote_source = true;
2274   expected_remote_audio_track.ended = false;
2275   expected_remote_audio_track.detached = false;
2276   expected_remote_audio_track.audio_level = 16383.0 / 32767.0;  // [0,1]
2277   expected_remote_audio_track.total_audio_energy = 0.125;
2278   expected_remote_audio_track.total_samples_received = 4567;
2279   expected_remote_audio_track.total_samples_duration = 0.25;
2280   expected_remote_audio_track.concealed_samples = 123;
2281   expected_remote_audio_track.concealment_events = 12;
2282   expected_remote_audio_track.inserted_samples_for_deceleration = 987;
2283   expected_remote_audio_track.removed_samples_for_acceleration = 876;
2284   expected_remote_audio_track.silent_concealed_samples = 765;
2285   expected_remote_audio_track.jitter_buffer_delay = 3.456;
2286   expected_remote_audio_track.jitter_buffer_emitted_count = 13;
2287   ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
2288   EXPECT_EQ(expected_remote_audio_track,
2289             report->Get(expected_remote_audio_track.id())
2290                 ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>());
2291 }
2292 
TEST_F(RTCStatsCollectorTest,CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video)2293 TEST_F(RTCStatsCollectorTest,
2294        CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
2295   rtc::scoped_refptr<MediaStream> local_stream =
2296       MediaStream::Create("LocalStreamId");
2297   pc_->mutable_local_streams()->AddStream(local_stream);
2298 
2299   // Local video track
2300   rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
2301       CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
2302                       MediaStreamTrackInterface::kLive);
2303   local_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
2304       static_cast<VideoTrackInterface*>(local_video_track.get())));
2305 
2306   cricket::VideoSenderInfo video_sender_info_ssrc1;
2307   video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
2308   video_sender_info_ssrc1.local_stats[0].ssrc = 1;
2309   video_sender_info_ssrc1.send_frame_width = 1234;
2310   video_sender_info_ssrc1.send_frame_height = 4321;
2311   video_sender_info_ssrc1.frames_encoded = 11;
2312   video_sender_info_ssrc1.huge_frames_sent = 1;
2313 
2314   stats_->CreateMockRtpSendersReceiversAndChannels(
2315       {}, {},
2316       {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
2317       {local_stream->id()}, {});
2318 
2319   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2320 
2321   auto stats_of_my_type =
2322       report->GetStatsOfType<DEPRECATED_RTCMediaStreamStats>();
2323   ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
2324   auto stats_of_track_type =
2325       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
2326   ASSERT_EQ(1U, stats_of_track_type.size())
2327       << "Wrong number of tracks in " << report->ToJson();
2328 
2329   DEPRECATED_RTCMediaStreamStats expected_local_stream(
2330       stats_of_my_type[0]->id(), report->timestamp_us());
2331   expected_local_stream.stream_identifier = local_stream->id();
2332   expected_local_stream.track_ids =
2333       std::vector<std::string>({stats_of_track_type[0]->id()});
2334   ASSERT_TRUE(report->Get(expected_local_stream.id()));
2335   EXPECT_EQ(expected_local_stream,
2336             report->Get(expected_local_stream.id())
2337                 ->cast_to<DEPRECATED_RTCMediaStreamStats>());
2338 
2339   DEPRECATED_RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
2340       stats_of_track_type[0]->id(), report->timestamp_us(),
2341       RTCMediaStreamTrackKind::kVideo);
2342   expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
2343   expected_local_video_track_ssrc1.media_source_id =
2344       "SV11";  // Attachment ID = SSRC + 10
2345   expected_local_video_track_ssrc1.remote_source = false;
2346   expected_local_video_track_ssrc1.ended = false;
2347   expected_local_video_track_ssrc1.detached = false;
2348   expected_local_video_track_ssrc1.frame_width = 1234;
2349   expected_local_video_track_ssrc1.frame_height = 4321;
2350   expected_local_video_track_ssrc1.frames_sent = 11;
2351   expected_local_video_track_ssrc1.huge_frames_sent = 1;
2352   ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
2353   EXPECT_EQ(expected_local_video_track_ssrc1,
2354             report->Get(expected_local_video_track_ssrc1.id())
2355                 ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>());
2356 }
2357 
TEST_F(RTCStatsCollectorTest,CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video)2358 TEST_F(RTCStatsCollectorTest,
2359        CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
2360   rtc::scoped_refptr<MediaStream> remote_stream =
2361       MediaStream::Create("RemoteStreamId");
2362   pc_->mutable_remote_streams()->AddStream(remote_stream);
2363 
2364   // Remote video track with values
2365   rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
2366       CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
2367                       MediaStreamTrackInterface::kEnded);
2368   remote_stream->AddTrack(rtc::scoped_refptr<VideoTrackInterface>(
2369       static_cast<VideoTrackInterface*>(remote_video_track_ssrc3.get())));
2370 
2371   cricket::VideoReceiverInfo video_receiver_info_ssrc3;
2372   video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
2373   video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
2374   video_receiver_info_ssrc3.frame_width = 6789;
2375   video_receiver_info_ssrc3.frame_height = 9876;
2376   video_receiver_info_ssrc3.jitter_buffer_delay_seconds = 2.5;
2377   video_receiver_info_ssrc3.jitter_buffer_emitted_count = 25;
2378   video_receiver_info_ssrc3.frames_received = 1000;
2379   video_receiver_info_ssrc3.frames_decoded = 995;
2380   video_receiver_info_ssrc3.frames_dropped = 10;
2381   video_receiver_info_ssrc3.frames_rendered = 990;
2382 
2383   stats_->CreateMockRtpSendersReceiversAndChannels(
2384       {}, {}, {},
2385       {std::make_pair(remote_video_track_ssrc3.get(),
2386                       video_receiver_info_ssrc3)},
2387       {}, {remote_stream});
2388 
2389   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2390 
2391   auto stats_of_my_type =
2392       report->GetStatsOfType<DEPRECATED_RTCMediaStreamStats>();
2393   ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
2394   auto stats_of_track_type =
2395       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
2396   ASSERT_EQ(1U, stats_of_track_type.size())
2397       << "Wrong number of tracks in " << report->ToJson();
2398   ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
2399 
2400   DEPRECATED_RTCMediaStreamStats expected_remote_stream(
2401       stats_of_my_type[0]->id(), report->timestamp_us());
2402   expected_remote_stream.stream_identifier = remote_stream->id();
2403   expected_remote_stream.track_ids =
2404       std::vector<std::string>({stats_of_track_type[0]->id()});
2405   ASSERT_TRUE(report->Get(expected_remote_stream.id()));
2406   EXPECT_EQ(expected_remote_stream,
2407             report->Get(expected_remote_stream.id())
2408                 ->cast_to<DEPRECATED_RTCMediaStreamStats>());
2409 
2410   DEPRECATED_RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
2411       stats_of_track_type[0]->id(), report->timestamp_us(),
2412       RTCMediaStreamTrackKind::kVideo);
2413   expected_remote_video_track_ssrc3.track_identifier =
2414       remote_video_track_ssrc3->id();
2415   // `expected_remote_video_track_ssrc3.media_source_id` should be undefined
2416   // because the track is remote.
2417   expected_remote_video_track_ssrc3.remote_source = true;
2418   expected_remote_video_track_ssrc3.ended = true;
2419   expected_remote_video_track_ssrc3.detached = false;
2420   expected_remote_video_track_ssrc3.frame_width = 6789;
2421   expected_remote_video_track_ssrc3.frame_height = 9876;
2422   expected_remote_video_track_ssrc3.jitter_buffer_delay = 2.5;
2423   expected_remote_video_track_ssrc3.jitter_buffer_emitted_count = 25;
2424   expected_remote_video_track_ssrc3.frames_received = 1000;
2425   expected_remote_video_track_ssrc3.frames_decoded = 995;
2426   expected_remote_video_track_ssrc3.frames_dropped = 10;
2427 
2428   ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
2429   EXPECT_EQ(expected_remote_video_track_ssrc3,
2430             report->Get(expected_remote_video_track_ssrc3.id())
2431                 ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>());
2432 }
2433 
TEST_F(RTCStatsCollectorTest,CollectRTCInboundRTPStreamStats_Audio)2434 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
2435   cricket::VoiceMediaInfo voice_media_info;
2436 
2437   voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
2438   voice_media_info.receivers[0].local_stats.push_back(
2439       cricket::SsrcReceiverInfo());
2440   voice_media_info.receivers[0].local_stats[0].ssrc = 1;
2441   voice_media_info.receivers[0].packets_lost = -1;  // Signed per RFC3550
2442   voice_media_info.receivers[0].packets_discarded = 7788;
2443   voice_media_info.receivers[0].packets_rcvd = 2;
2444   voice_media_info.receivers[0].nacks_sent = 5;
2445   voice_media_info.receivers[0].fec_packets_discarded = 5566;
2446   voice_media_info.receivers[0].fec_packets_received = 6677;
2447   voice_media_info.receivers[0].payload_bytes_rcvd = 3;
2448   voice_media_info.receivers[0].header_and_padding_bytes_rcvd = 4;
2449   voice_media_info.receivers[0].codec_payload_type = 42;
2450   voice_media_info.receivers[0].jitter_ms = 4500;
2451   voice_media_info.receivers[0].jitter_buffer_delay_seconds = 1.0;
2452   voice_media_info.receivers[0].jitter_buffer_target_delay_seconds = 1.1;
2453   voice_media_info.receivers[0].jitter_buffer_minimum_delay_seconds = 0.999;
2454   voice_media_info.receivers[0].jitter_buffer_emitted_count = 2;
2455   voice_media_info.receivers[0].total_samples_received = 3;
2456   voice_media_info.receivers[0].concealed_samples = 4;
2457   voice_media_info.receivers[0].silent_concealed_samples = 5;
2458   voice_media_info.receivers[0].concealment_events = 6;
2459   voice_media_info.receivers[0].inserted_samples_for_deceleration = 7;
2460   voice_media_info.receivers[0].removed_samples_for_acceleration = 8;
2461   voice_media_info.receivers[0].audio_level = 14442;  // [0,32767]
2462   voice_media_info.receivers[0].total_output_energy = 10.0;
2463   voice_media_info.receivers[0].total_output_duration = 11.0;
2464   voice_media_info.receivers[0].jitter_buffer_flushes = 7;
2465   voice_media_info.receivers[0].delayed_packet_outage_samples = 15;
2466   voice_media_info.receivers[0].relative_packet_arrival_delay_seconds = 16;
2467   voice_media_info.receivers[0].interruption_count = 7788;
2468   voice_media_info.receivers[0].total_interruption_duration_ms = 778899;
2469 
2470   voice_media_info.receivers[0].last_packet_received_timestamp_ms =
2471       absl::nullopt;
2472 
2473   RtpCodecParameters codec_parameters;
2474   codec_parameters.payload_type = 42;
2475   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2476   codec_parameters.name = "dummy";
2477   codec_parameters.clock_rate = 0;
2478   voice_media_info.receive_codecs.insert(
2479       std::make_pair(codec_parameters.payload_type, codec_parameters));
2480 
2481   auto* voice_media_channel =
2482       pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
2483   stats_->SetupRemoteTrackAndReceiver(
2484       cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1);
2485 
2486   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2487 
2488   auto stats_of_track_type =
2489       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
2490   ASSERT_EQ(1U, stats_of_track_type.size());
2491 
2492   RTCInboundRTPStreamStats expected_audio("ITTransportName1A1",
2493                                           report->timestamp_us());
2494   expected_audio.ssrc = 1;
2495   expected_audio.media_type = "audio";
2496   expected_audio.kind = "audio";
2497   expected_audio.track_identifier = "RemoteAudioTrackID";
2498   expected_audio.mid = "AudioMid";
2499   expected_audio.track_id = stats_of_track_type[0]->id();
2500   expected_audio.transport_id = "TTransportName1";
2501   expected_audio.codec_id = "CITTransportName1_42";
2502   expected_audio.packets_received = 2;
2503   expected_audio.nack_count = 5;
2504   expected_audio.fec_packets_discarded = 5566;
2505   expected_audio.fec_packets_received = 6677;
2506   expected_audio.bytes_received = 3;
2507   expected_audio.header_bytes_received = 4;
2508   expected_audio.packets_lost = -1;
2509   expected_audio.packets_discarded = 7788;
2510   // `expected_audio.last_packet_received_timestamp` should be undefined.
2511   expected_audio.jitter = 4.5;
2512   expected_audio.jitter_buffer_delay = 1.0;
2513   expected_audio.jitter_buffer_target_delay = 1.1;
2514   expected_audio.jitter_buffer_minimum_delay = 0.999;
2515   expected_audio.jitter_buffer_emitted_count = 2;
2516   expected_audio.total_samples_received = 3;
2517   expected_audio.concealed_samples = 4;
2518   expected_audio.silent_concealed_samples = 5;
2519   expected_audio.concealment_events = 6;
2520   expected_audio.inserted_samples_for_deceleration = 7;
2521   expected_audio.removed_samples_for_acceleration = 8;
2522   expected_audio.audio_level = 14442.0 / 32767.0;  // [0,1]
2523   expected_audio.total_audio_energy = 10.0;
2524   expected_audio.total_samples_duration = 11.0;
2525   expected_audio.jitter_buffer_flushes = 7;
2526   expected_audio.delayed_packet_outage_samples = 15;
2527   expected_audio.relative_packet_arrival_delay = 16;
2528   expected_audio.interruption_count = 7788;
2529   expected_audio.total_interruption_duration = 778.899;
2530 
2531   ASSERT_TRUE(report->Get(expected_audio.id()));
2532   EXPECT_EQ(
2533       report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
2534       expected_audio);
2535 
2536   // Set previously undefined values and "GetStats" again.
2537   voice_media_info.receivers[0].last_packet_received_timestamp_ms = 3000;
2538   expected_audio.last_packet_received_timestamp = 3000.0;
2539   voice_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 4567;
2540   expected_audio.estimated_playout_timestamp = 4567;
2541   voice_media_channel->SetStats(voice_media_info);
2542 
2543   report = stats_->GetFreshStatsReport();
2544 
2545   ASSERT_TRUE(report->Get(expected_audio.id()));
2546   EXPECT_EQ(
2547       report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
2548       expected_audio);
2549   EXPECT_TRUE(report->Get(*expected_audio.track_id));
2550   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2551   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2552 }
2553 
TEST_F(RTCStatsCollectorTest,CollectRTCInboundRTPStreamStats_Video)2554 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
2555   cricket::VideoMediaInfo video_media_info;
2556 
2557   video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
2558   video_media_info.receivers[0].local_stats.push_back(
2559       cricket::SsrcReceiverInfo());
2560   video_media_info.receivers[0].local_stats[0].ssrc = 1;
2561   video_media_info.receivers[0].packets_rcvd = 2;
2562   video_media_info.receivers[0].packets_lost = 42;
2563   video_media_info.receivers[0].payload_bytes_rcvd = 3;
2564   video_media_info.receivers[0].header_and_padding_bytes_rcvd = 12;
2565   video_media_info.receivers[0].codec_payload_type = 42;
2566   video_media_info.receivers[0].firs_sent = 5;
2567   video_media_info.receivers[0].plis_sent = 6;
2568   video_media_info.receivers[0].nacks_sent = 7;
2569   video_media_info.receivers[0].frames_received = 8;
2570   video_media_info.receivers[0].frames_decoded = 9;
2571   video_media_info.receivers[0].key_frames_decoded = 3;
2572   video_media_info.receivers[0].frames_dropped = 13;
2573   video_media_info.receivers[0].qp_sum = absl::nullopt;
2574   video_media_info.receivers[0].total_decode_time =
2575       webrtc::TimeDelta::Seconds(9);
2576   video_media_info.receivers[0].total_processing_delay =
2577       webrtc::TimeDelta::Millis(600);
2578   video_media_info.receivers[0].total_assembly_time =
2579       webrtc::TimeDelta::Millis(500);
2580   video_media_info.receivers[0].frames_assembled_from_multiple_packets = 23;
2581   video_media_info.receivers[0].total_inter_frame_delay = 0.123;
2582   video_media_info.receivers[0].total_squared_inter_frame_delay = 0.00456;
2583   video_media_info.receivers[0].pause_count = 2;
2584   video_media_info.receivers[0].total_pauses_duration_ms = 10000;
2585   video_media_info.receivers[0].freeze_count = 3;
2586   video_media_info.receivers[0].total_freezes_duration_ms = 1000;
2587   video_media_info.receivers[0].jitter_ms = 1199;
2588   video_media_info.receivers[0].jitter_buffer_delay_seconds = 3.456;
2589   video_media_info.receivers[0].jitter_buffer_target_delay_seconds = 1.1;
2590   video_media_info.receivers[0].jitter_buffer_minimum_delay_seconds = 0.999;
2591   video_media_info.receivers[0].jitter_buffer_emitted_count = 13;
2592 
2593   video_media_info.receivers[0].last_packet_received_timestamp_ms =
2594       absl::nullopt;
2595   video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
2596   video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms =
2597       absl::nullopt;
2598   video_media_info.receivers[0].decoder_implementation_name = "";
2599   video_media_info.receivers[0].min_playout_delay_ms = 50;
2600   video_media_info.receivers[0].power_efficient_decoder = false;
2601 
2602   // Note: these two values intentionally differ,
2603   // only the decoded one should show up.
2604   video_media_info.receivers[0].framerate_rcvd = 15;
2605   video_media_info.receivers[0].framerate_decoded = 5;
2606 
2607   RtpCodecParameters codec_parameters;
2608   codec_parameters.payload_type = 42;
2609   codec_parameters.kind = cricket::MEDIA_TYPE_VIDEO;
2610   codec_parameters.name = "dummy";
2611   codec_parameters.clock_rate = 0;
2612   video_media_info.receive_codecs.insert(
2613       std::make_pair(codec_parameters.payload_type, codec_parameters));
2614 
2615   auto* video_media_channel =
2616       pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
2617   stats_->SetupRemoteTrackAndReceiver(
2618       cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
2619 
2620   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2621 
2622   RTCInboundRTPStreamStats expected_video("ITTransportName1V1",
2623                                           report->timestamp_us());
2624   expected_video.ssrc = 1;
2625   expected_video.media_type = "video";
2626   expected_video.kind = "video";
2627   expected_video.track_identifier = "RemoteVideoTrackID";
2628   expected_video.mid = "VideoMid";
2629   expected_video.track_id =
2630       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get());
2631   expected_video.transport_id = "TTransportName1";
2632   expected_video.codec_id = "CITTransportName1_42";
2633   expected_video.fir_count = 5;
2634   expected_video.pli_count = 6;
2635   expected_video.nack_count = 7;
2636   expected_video.packets_received = 2;
2637   expected_video.bytes_received = 3;
2638   expected_video.header_bytes_received = 12;
2639   expected_video.packets_lost = 42;
2640   expected_video.frames_received = 8;
2641   expected_video.frames_decoded = 9;
2642   expected_video.key_frames_decoded = 3;
2643   expected_video.frames_dropped = 13;
2644   // `expected_video.qp_sum` should be undefined.
2645   expected_video.total_decode_time = 9.0;
2646   expected_video.total_processing_delay = 0.6;
2647   expected_video.total_assembly_time = 0.5;
2648   expected_video.frames_assembled_from_multiple_packets = 23;
2649   expected_video.total_inter_frame_delay = 0.123;
2650   expected_video.total_squared_inter_frame_delay = 0.00456;
2651   expected_video.pause_count = 2;
2652   expected_video.total_pauses_duration = 10;
2653   expected_video.freeze_count = 3;
2654   expected_video.total_freezes_duration = 1;
2655   expected_video.jitter = 1.199;
2656   expected_video.jitter_buffer_delay = 3.456;
2657   expected_video.jitter_buffer_target_delay = 1.1;
2658   expected_video.jitter_buffer_minimum_delay = 0.999;
2659   expected_video.jitter_buffer_emitted_count = 13;
2660   // `expected_video.last_packet_received_timestamp` should be undefined.
2661   // `expected_video.content_type` should be undefined.
2662   // `expected_video.decoder_implementation` should be undefined.
2663   expected_video.min_playout_delay = 0.05;
2664   expected_video.frames_per_second = 5;
2665   expected_video.power_efficient_decoder = false;
2666 
2667   ASSERT_TRUE(report->Get(expected_video.id()));
2668   EXPECT_EQ(
2669       report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
2670       expected_video);
2671 
2672   // Set previously undefined values and "GetStats" again.
2673   video_media_info.receivers[0].qp_sum = 9;
2674   expected_video.qp_sum = 9;
2675   video_media_info.receivers[0].last_packet_received_timestamp_ms = 1000;
2676   expected_video.last_packet_received_timestamp = 1000.0;
2677   video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
2678   expected_video.content_type = "screenshare";
2679   video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 1234;
2680   expected_video.estimated_playout_timestamp = 1234;
2681   video_media_info.receivers[0].decoder_implementation_name = "libfoodecoder";
2682   expected_video.decoder_implementation = "libfoodecoder";
2683   video_media_info.receivers[0].power_efficient_decoder = true;
2684   expected_video.power_efficient_decoder = true;
2685   video_media_channel->SetStats(video_media_info);
2686 
2687   report = stats_->GetFreshStatsReport();
2688 
2689   ASSERT_TRUE(report->Get(expected_video.id()));
2690   EXPECT_EQ(
2691       report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
2692       expected_video);
2693   EXPECT_TRUE(report->Get(*expected_video.track_id));
2694   EXPECT_TRUE(report->Get(*expected_video.transport_id));
2695   EXPECT_TRUE(report->Get(*expected_video.codec_id));
2696 }
2697 
TEST_F(RTCStatsCollectorTest,CollectGoogTimingFrameInfo)2698 TEST_F(RTCStatsCollectorTest, CollectGoogTimingFrameInfo) {
2699   cricket::VideoMediaInfo video_media_info;
2700 
2701   video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
2702   video_media_info.receivers[0].local_stats.push_back(
2703       cricket::SsrcReceiverInfo());
2704   video_media_info.receivers[0].local_stats[0].ssrc = 1;
2705   TimingFrameInfo timing_frame_info;
2706   timing_frame_info.rtp_timestamp = 1;
2707   timing_frame_info.capture_time_ms = 2;
2708   timing_frame_info.encode_start_ms = 3;
2709   timing_frame_info.encode_finish_ms = 4;
2710   timing_frame_info.packetization_finish_ms = 5;
2711   timing_frame_info.pacer_exit_ms = 6;
2712   timing_frame_info.network_timestamp_ms = 7;
2713   timing_frame_info.network2_timestamp_ms = 8;
2714   timing_frame_info.receive_start_ms = 9;
2715   timing_frame_info.receive_finish_ms = 10;
2716   timing_frame_info.decode_start_ms = 11;
2717   timing_frame_info.decode_finish_ms = 12;
2718   timing_frame_info.render_time_ms = 13;
2719   timing_frame_info.flags = 14;
2720   video_media_info.receivers[0].timing_frame_info = timing_frame_info;
2721 
2722   pc_->AddVideoChannel("Mid0", "Transport0", video_media_info);
2723   stats_->SetupRemoteTrackAndReceiver(
2724       cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
2725 
2726   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2727   auto inbound_rtps = report->GetStatsOfType<RTCInboundRTPStreamStats>();
2728   ASSERT_EQ(inbound_rtps.size(), 1u);
2729   ASSERT_TRUE(inbound_rtps[0]->goog_timing_frame_info.is_defined());
2730   EXPECT_EQ(*inbound_rtps[0]->goog_timing_frame_info,
2731             "1,2,3,4,5,6,7,8,9,10,11,12,13,1,0");
2732 }
2733 
TEST_F(RTCStatsCollectorTest,CollectRTCOutboundRTPStreamStats_Audio)2734 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
2735   cricket::VoiceMediaInfo voice_media_info;
2736 
2737   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2738   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2739   voice_media_info.senders[0].local_stats[0].ssrc = 1;
2740   voice_media_info.senders[0].packets_sent = 2;
2741   voice_media_info.senders[0].total_packet_send_delay = TimeDelta::Seconds(1);
2742   voice_media_info.senders[0].retransmitted_packets_sent = 20;
2743   voice_media_info.senders[0].payload_bytes_sent = 3;
2744   voice_media_info.senders[0].header_and_padding_bytes_sent = 12;
2745   voice_media_info.senders[0].retransmitted_bytes_sent = 30;
2746   voice_media_info.senders[0].nacks_rcvd = 31;
2747   voice_media_info.senders[0].target_bitrate = 32000;
2748   voice_media_info.senders[0].codec_payload_type = 42;
2749   voice_media_info.senders[0].active = true;
2750 
2751   RtpCodecParameters codec_parameters;
2752   codec_parameters.payload_type = 42;
2753   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2754   codec_parameters.name = "dummy";
2755   codec_parameters.clock_rate = 0;
2756   voice_media_info.send_codecs.insert(
2757       std::make_pair(codec_parameters.payload_type, codec_parameters));
2758 
2759   pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
2760   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
2761                                    "LocalAudioTrackID", 1, true,
2762                                    /*attachment_id=*/50);
2763 
2764   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2765 
2766   RTCOutboundRTPStreamStats expected_audio("OTTransportName1A1",
2767                                            report->timestamp_us());
2768   expected_audio.media_source_id = "SA50";
2769   // `expected_audio.remote_id` should be undefined.
2770   expected_audio.mid = "AudioMid";
2771   expected_audio.ssrc = 1;
2772   expected_audio.media_type = "audio";
2773   expected_audio.kind = "audio";
2774   expected_audio.track_id =
2775       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get());
2776   expected_audio.transport_id = "TTransportName1";
2777   expected_audio.codec_id = "COTTransportName1_42";
2778   expected_audio.packets_sent = 2;
2779   expected_audio.total_packet_send_delay = 1;
2780   expected_audio.retransmitted_packets_sent = 20;
2781   expected_audio.bytes_sent = 3;
2782   expected_audio.header_bytes_sent = 12;
2783   expected_audio.retransmitted_bytes_sent = 30;
2784   expected_audio.nack_count = 31;
2785   expected_audio.target_bitrate = 32000;
2786   expected_audio.active = true;
2787 
2788   ASSERT_TRUE(report->Get(expected_audio.id()));
2789   EXPECT_EQ(
2790       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2791       expected_audio);
2792 
2793   ASSERT_TRUE(report->Get(expected_audio.id()));
2794   EXPECT_EQ(
2795       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2796       expected_audio);
2797   EXPECT_TRUE(report->Get(*expected_audio.track_id));
2798   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2799   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2800 }
2801 
TEST_F(RTCStatsCollectorTest,CollectRTCOutboundRTPStreamStats_Video)2802 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
2803   cricket::VideoMediaInfo video_media_info;
2804 
2805   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2806   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2807   video_media_info.senders[0].local_stats[0].ssrc = 1;
2808   video_media_info.senders[0].firs_rcvd = 2;
2809   video_media_info.senders[0].plis_rcvd = 3;
2810   video_media_info.senders[0].nacks_rcvd = 4;
2811   video_media_info.senders[0].packets_sent = 5;
2812   video_media_info.senders[0].retransmitted_packets_sent = 50;
2813   video_media_info.senders[0].payload_bytes_sent = 6;
2814   video_media_info.senders[0].header_and_padding_bytes_sent = 12;
2815   video_media_info.senders[0].retransmitted_bytes_sent = 60;
2816   video_media_info.senders[0].codec_payload_type = 42;
2817   video_media_info.senders[0].frames_encoded = 8;
2818   video_media_info.senders[0].key_frames_encoded = 3;
2819   video_media_info.senders[0].total_encode_time_ms = 9000;
2820   video_media_info.senders[0].total_encoded_bytes_target = 1234;
2821   video_media_info.senders[0].total_packet_send_delay =
2822       webrtc::TimeDelta::Seconds(10);
2823   video_media_info.senders[0].quality_limitation_reason =
2824       QualityLimitationReason::kBandwidth;
2825   video_media_info.senders[0].quality_limitation_durations_ms
2826       [webrtc::QualityLimitationReason::kBandwidth] = 300;
2827   video_media_info.senders[0].quality_limitation_resolution_changes = 56u;
2828   video_media_info.senders[0].qp_sum = absl::nullopt;
2829   video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
2830   video_media_info.senders[0].encoder_implementation_name = "";
2831   video_media_info.senders[0].power_efficient_encoder = false;
2832   video_media_info.senders[0].send_frame_width = 200;
2833   video_media_info.senders[0].send_frame_height = 100;
2834   video_media_info.senders[0].framerate_sent = 10;
2835   video_media_info.senders[0].frames_sent = 5;
2836   video_media_info.senders[0].huge_frames_sent = 2;
2837   video_media_info.senders[0].active = false;
2838   video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
2839   RtpCodecParameters codec_parameters;
2840   codec_parameters.payload_type = 42;
2841   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2842   codec_parameters.name = "dummy";
2843   codec_parameters.clock_rate = 0;
2844   video_media_info.send_codecs.insert(
2845       std::make_pair(codec_parameters.payload_type, codec_parameters));
2846 
2847   auto* video_media_channel =
2848       pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
2849   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
2850                                    "LocalVideoTrackID", 1, true,
2851                                    /*attachment_id=*/50);
2852 
2853   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2854 
2855   auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
2856   ASSERT_EQ(1U, stats_of_my_type.size());
2857   auto stats_of_track_type =
2858       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
2859   ASSERT_EQ(1U, stats_of_track_type.size());
2860 
2861   RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
2862                                            report->timestamp_us());
2863   expected_video.media_source_id = "SV50";
2864   // `expected_video.remote_id` should be undefined.
2865   expected_video.mid = "VideoMid";
2866   expected_video.ssrc = 1;
2867   expected_video.media_type = "video";
2868   expected_video.kind = "video";
2869   expected_video.track_id = stats_of_track_type[0]->id();
2870   expected_video.transport_id = "TTransportName1";
2871   expected_video.codec_id = "COTTransportName1_42";
2872   expected_video.fir_count = 2;
2873   expected_video.pli_count = 3;
2874   expected_video.nack_count = 4;
2875   expected_video.packets_sent = 5;
2876   expected_video.retransmitted_packets_sent = 50;
2877   expected_video.bytes_sent = 6;
2878   expected_video.header_bytes_sent = 12;
2879   expected_video.retransmitted_bytes_sent = 60;
2880   expected_video.frames_encoded = 8;
2881   expected_video.key_frames_encoded = 3;
2882   expected_video.total_encode_time = 9.0;
2883   expected_video.total_encoded_bytes_target = 1234;
2884   expected_video.total_packet_send_delay = 10.0;
2885   expected_video.quality_limitation_reason = "bandwidth";
2886   expected_video.quality_limitation_durations = std::map<std::string, double>{
2887       std::pair<std::string, double>{"bandwidth", 0.3},
2888   };
2889   expected_video.quality_limitation_resolution_changes = 56u;
2890   expected_video.frame_width = 200u;
2891   expected_video.frame_height = 100u;
2892   expected_video.frames_per_second = 10.0;
2893   expected_video.frames_sent = 5;
2894   expected_video.huge_frames_sent = 2;
2895   expected_video.active = false;
2896   expected_video.power_efficient_encoder = false;
2897   // `expected_video.content_type` should be undefined.
2898   // `expected_video.qp_sum` should be undefined.
2899   // `expected_video.encoder_implementation` should be undefined.
2900   ASSERT_TRUE(report->Get(expected_video.id()));
2901 
2902   EXPECT_EQ(
2903       report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2904       expected_video);
2905 
2906   // Set previously undefined values and "GetStats" again.
2907   video_media_info.senders[0].qp_sum = 9;
2908   expected_video.qp_sum = 9;
2909   video_media_info.senders[0].content_type = VideoContentType::SCREENSHARE;
2910   expected_video.content_type = "screenshare";
2911   video_media_info.senders[0].encoder_implementation_name = "libfooencoder";
2912   video_media_info.aggregated_senders[0] = video_media_info.senders[0];
2913   expected_video.encoder_implementation = "libfooencoder";
2914   video_media_info.senders[0].power_efficient_encoder = true;
2915   expected_video.power_efficient_encoder = true;
2916   video_media_channel->SetStats(video_media_info);
2917 
2918   report = stats_->GetFreshStatsReport();
2919 
2920   ASSERT_TRUE(report->Get(expected_video.id()));
2921   EXPECT_EQ(
2922       report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2923       expected_video);
2924   EXPECT_TRUE(report->Get(*expected_video.track_id));
2925   EXPECT_TRUE(report->Get(*expected_video.transport_id));
2926   EXPECT_TRUE(report->Get(*expected_video.codec_id));
2927 }
2928 
TEST_F(RTCStatsCollectorTest,CollectRTCTransportStats)2929 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
2930   const char kTransportName[] = "transport";
2931 
2932   pc_->AddVoiceChannel("audio", kTransportName);
2933 
2934   std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2935       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2936                           cricket::LOCAL_PORT_TYPE, 42);
2937   std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2938       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2939                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2940                           42);
2941   std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
2942       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2943                           cricket::LOCAL_PORT_TYPE, 42);
2944   std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2945       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2946                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2947                           42);
2948 
2949   cricket::ConnectionInfo rtp_connection_info;
2950   rtp_connection_info.best_connection = false;
2951   rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2952   rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
2953   rtp_connection_info.sent_total_bytes = 42;
2954   rtp_connection_info.recv_total_bytes = 1337;
2955   rtp_connection_info.sent_total_packets = 3;
2956   rtp_connection_info.sent_discarded_packets = 2;
2957   rtp_connection_info.packets_received = 4;
2958   cricket::TransportChannelStats rtp_transport_channel_stats;
2959   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2960   rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2961       rtp_connection_info);
2962   rtp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
2963   rtp_transport_channel_stats.ice_transport_stats.bytes_sent = 42;
2964   rtp_transport_channel_stats.ice_transport_stats.packets_sent = 1;
2965   rtp_transport_channel_stats.ice_transport_stats.bytes_received = 1337;
2966   rtp_transport_channel_stats.ice_transport_stats.packets_received = 4;
2967   rtp_transport_channel_stats.ice_transport_stats
2968       .selected_candidate_pair_changes = 1;
2969   rtp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
2970       "thelocalufrag";
2971   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
2972 
2973   // Get stats without RTCP, an active connection or certificates.
2974   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2975 
2976   RTCTransportStats expected_rtp_transport(
2977       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
2978       report->timestamp_us());
2979   expected_rtp_transport.bytes_sent = 42;
2980   expected_rtp_transport.packets_sent = 1;
2981   expected_rtp_transport.bytes_received = 1337;
2982   expected_rtp_transport.packets_received = 4;
2983   expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
2984   expected_rtp_transport.dtls_role = RTCDtlsRole::kUnknown;
2985   expected_rtp_transport.selected_candidate_pair_changes = 1;
2986   expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
2987   expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
2988   expected_rtp_transport.ice_state = RTCIceTransportState::kNew;
2989 
2990   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2991   EXPECT_EQ(
2992       expected_rtp_transport,
2993       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2994 
2995   cricket::ConnectionInfo rtcp_connection_info;
2996   rtcp_connection_info.best_connection = false;
2997   rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
2998   rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
2999   rtcp_connection_info.sent_total_bytes = 1337;
3000   rtcp_connection_info.recv_total_bytes = 42;
3001   rtcp_connection_info.sent_total_packets = 3;
3002   rtcp_connection_info.sent_discarded_packets = 2;
3003   rtcp_connection_info.packets_received = 4;
3004   cricket::TransportChannelStats rtcp_transport_channel_stats;
3005   rtcp_transport_channel_stats.component =
3006       cricket::ICE_CANDIDATE_COMPONENT_RTCP;
3007   rtcp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
3008       rtcp_connection_info);
3009   rtcp_transport_channel_stats.dtls_state = DtlsTransportState::kConnecting;
3010   rtcp_transport_channel_stats.ice_transport_stats.bytes_sent = 1337;
3011   rtcp_transport_channel_stats.ice_transport_stats.packets_sent = 1;
3012   rtcp_transport_channel_stats.ice_transport_stats.bytes_received = 42;
3013   rtcp_transport_channel_stats.ice_transport_stats.packets_received = 4;
3014   rtcp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
3015       "thelocalufrag";
3016   rtcp_transport_channel_stats.ice_transport_stats.ice_state =
3017       IceTransportState::kChecking;
3018   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
3019                                           rtcp_transport_channel_stats});
3020 
3021   // Get stats with RTCP and without an active connection or certificates.
3022   report = stats_->GetFreshStatsReport();
3023 
3024   RTCTransportStats expected_rtcp_transport(
3025       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
3026       report->timestamp_us());
3027   expected_rtcp_transport.bytes_sent = 1337;
3028   expected_rtcp_transport.packets_sent = 1;
3029   expected_rtcp_transport.bytes_received = 42;
3030   expected_rtcp_transport.packets_received = 4;
3031   expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
3032   expected_rtcp_transport.dtls_role = RTCDtlsRole::kUnknown;
3033   expected_rtcp_transport.selected_candidate_pair_changes = 0;
3034   expected_rtcp_transport.ice_role = RTCIceRole::kUnknown;
3035   expected_rtcp_transport.ice_local_username_fragment = "thelocalufrag";
3036   expected_rtcp_transport.ice_state = RTCIceTransportState::kChecking;
3037 
3038   expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
3039   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
3040   EXPECT_EQ(
3041       expected_rtp_transport,
3042       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
3043   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
3044   EXPECT_EQ(
3045       expected_rtcp_transport,
3046       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
3047 
3048   // Get stats with an active connection (selected candidate pair).
3049   rtcp_transport_channel_stats.ice_transport_stats.connection_infos[0]
3050       .best_connection = true;
3051   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
3052                                           rtcp_transport_channel_stats});
3053 
3054   report = stats_->GetFreshStatsReport();
3055 
3056   expected_rtcp_transport.selected_candidate_pair_id =
3057       "CP" + rtcp_local_candidate->id() + "_" + rtcp_remote_candidate->id();
3058 
3059   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
3060   EXPECT_EQ(
3061       expected_rtp_transport,
3062       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
3063   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
3064   EXPECT_EQ(
3065       expected_rtcp_transport,
3066       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
3067 
3068   // Get stats with certificates.
3069   std::unique_ptr<CertificateInfo> local_certinfo =
3070       CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
3071   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
3072   std::unique_ptr<CertificateInfo> remote_certinfo =
3073       CreateFakeCertificateAndInfoFromDers(
3074           {"(remote) local", "(remote) chain"});
3075   pc_->SetRemoteCertChain(
3076       kTransportName,
3077       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
3078 
3079   report = stats_->GetFreshStatsReport();
3080 
3081   expected_rtp_transport.local_certificate_id =
3082       "CF" + local_certinfo->fingerprints[0];
3083   expected_rtp_transport.remote_certificate_id =
3084       "CF" + remote_certinfo->fingerprints[0];
3085 
3086   expected_rtcp_transport.local_certificate_id =
3087       *expected_rtp_transport.local_certificate_id;
3088   expected_rtcp_transport.remote_certificate_id =
3089       *expected_rtp_transport.remote_certificate_id;
3090 
3091   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
3092   EXPECT_EQ(
3093       expected_rtp_transport,
3094       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
3095   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
3096   EXPECT_EQ(
3097       expected_rtcp_transport,
3098       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
3099 }
3100 
TEST_F(RTCStatsCollectorTest,CollectRTCTransportStatsWithCrypto)3101 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) {
3102   const char kTransportName[] = "transport";
3103 
3104   pc_->AddVoiceChannel("audio", kTransportName);
3105 
3106   std::unique_ptr<cricket::Candidate> rtp_local_candidate =
3107       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
3108                           cricket::LOCAL_PORT_TYPE, 42);
3109   std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
3110       CreateFakeCandidate("42.42.42.42", 42, "protocol",
3111                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
3112                           42);
3113   std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
3114       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
3115                           cricket::LOCAL_PORT_TYPE, 42);
3116   std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
3117       CreateFakeCandidate("42.42.42.42", 42, "protocol",
3118                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
3119                           42);
3120 
3121   cricket::ConnectionInfo rtp_connection_info;
3122   rtp_connection_info.best_connection = false;
3123   rtp_connection_info.local_candidate = *rtp_local_candidate.get();
3124   rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
3125   cricket::TransportChannelStats rtp_transport_channel_stats;
3126   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
3127   rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
3128       rtp_connection_info);
3129   // The state must be connected in order for crypto parameters to show up.
3130   rtp_transport_channel_stats.dtls_state = DtlsTransportState::kConnected;
3131   rtp_transport_channel_stats.ice_transport_stats
3132       .selected_candidate_pair_changes = 1;
3133   rtp_transport_channel_stats.ssl_version_bytes = 0x0203;
3134   rtp_transport_channel_stats.dtls_role = rtc::SSL_CLIENT;
3135   rtp_transport_channel_stats.ice_transport_stats.ice_role =
3136       cricket::ICEROLE_CONTROLLING;
3137   rtp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment =
3138       "thelocalufrag";
3139   rtp_transport_channel_stats.ice_transport_stats.ice_state =
3140       IceTransportState::kConnected;
3141   // 0x2F is TLS_RSA_WITH_AES_128_CBC_SHA according to IANA
3142   rtp_transport_channel_stats.ssl_cipher_suite = 0x2F;
3143   rtp_transport_channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80;
3144   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
3145 
3146   // Get stats
3147   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3148 
3149   RTCTransportStats expected_rtp_transport(
3150       "Ttransport" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
3151       report->timestamp_us());
3152   expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected;
3153   expected_rtp_transport.selected_candidate_pair_changes = 1;
3154   expected_rtp_transport.ice_role = RTCIceRole::kUnknown;
3155   expected_rtp_transport.bytes_sent = 0;
3156   expected_rtp_transport.bytes_received = 0;
3157   expected_rtp_transport.packets_sent = 0;
3158   expected_rtp_transport.packets_received = 0;
3159   expected_rtp_transport.ice_role = RTCIceRole::kControlling;
3160   expected_rtp_transport.ice_local_username_fragment = "thelocalufrag";
3161   expected_rtp_transport.ice_state = "connected";
3162   // Crypto parameters
3163   expected_rtp_transport.tls_version = "0203";
3164   expected_rtp_transport.dtls_role = RTCDtlsRole::kClient;
3165   expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA";
3166   expected_rtp_transport.srtp_cipher = "AES_CM_128_HMAC_SHA1_80";
3167 
3168   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
3169   EXPECT_EQ(
3170       expected_rtp_transport,
3171       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
3172 }
3173 
TEST_F(RTCStatsCollectorTest,CollectNoStreamRTCOutboundRTPStreamStats_Audio)3174 TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
3175   cricket::VoiceMediaInfo voice_media_info;
3176 
3177   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
3178   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3179   voice_media_info.senders[0].local_stats[0].ssrc = 1;
3180   voice_media_info.senders[0].packets_sent = 2;
3181   voice_media_info.senders[0].total_packet_send_delay = TimeDelta::Seconds(0.5);
3182   voice_media_info.senders[0].retransmitted_packets_sent = 20;
3183   voice_media_info.senders[0].payload_bytes_sent = 3;
3184   voice_media_info.senders[0].header_and_padding_bytes_sent = 4;
3185   voice_media_info.senders[0].retransmitted_bytes_sent = 30;
3186   voice_media_info.senders[0].nacks_rcvd = 31;
3187   voice_media_info.senders[0].codec_payload_type = 42;
3188   voice_media_info.senders[0].active = true;
3189 
3190   RtpCodecParameters codec_parameters;
3191   codec_parameters.payload_type = 42;
3192   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
3193   codec_parameters.name = "dummy";
3194   codec_parameters.clock_rate = 0;
3195   voice_media_info.send_codecs.insert(
3196       std::make_pair(codec_parameters.payload_type, codec_parameters));
3197 
3198   // Emulates the case where AddTrack is used without an associated MediaStream
3199   pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
3200   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
3201                                    "LocalAudioTrackID", 1, false,
3202                                    /*attachment_id=*/50);
3203 
3204   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3205 
3206   RTCOutboundRTPStreamStats expected_audio("OTTransportName1A1",
3207                                            report->timestamp_us());
3208   expected_audio.media_source_id = "SA50";
3209   expected_audio.mid = "AudioMid";
3210   expected_audio.ssrc = 1;
3211   expected_audio.media_type = "audio";
3212   expected_audio.kind = "audio";
3213   expected_audio.track_id =
3214       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get());
3215   expected_audio.transport_id = "TTransportName1";
3216   expected_audio.codec_id = "COTTransportName1_42";
3217   expected_audio.packets_sent = 2;
3218   expected_audio.total_packet_send_delay = 0.5;
3219   expected_audio.retransmitted_packets_sent = 20;
3220   expected_audio.bytes_sent = 3;
3221   expected_audio.header_bytes_sent = 4;
3222   expected_audio.retransmitted_bytes_sent = 30;
3223   expected_audio.nack_count = 31;
3224   expected_audio.active = true;
3225 
3226   ASSERT_TRUE(report->Get(expected_audio.id()));
3227   EXPECT_EQ(
3228       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
3229       expected_audio);
3230   EXPECT_TRUE(report->Get(*expected_audio.track_id));
3231   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
3232   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
3233 }
3234 
TEST_F(RTCStatsCollectorTest,RTCAudioSourceStatsCollectedForSenderWithTrack)3235 TEST_F(RTCStatsCollectorTest, RTCAudioSourceStatsCollectedForSenderWithTrack) {
3236   const uint32_t kSsrc = 4;
3237   const int kAttachmentId = 42;
3238 
3239   cricket::VoiceMediaInfo voice_media_info;
3240   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
3241   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3242   voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
3243   voice_media_info.senders[0].audio_level = 32767;  // [0,32767]
3244   voice_media_info.senders[0].total_input_energy = 2.0;
3245   voice_media_info.senders[0].total_input_duration = 3.0;
3246   voice_media_info.senders[0].apm_statistics.echo_return_loss = 42.0;
3247   voice_media_info.senders[0].apm_statistics.echo_return_loss_enhancement =
3248       52.0;
3249   pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
3250   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
3251                                    "LocalAudioTrackID", kSsrc, false,
3252                                    kAttachmentId);
3253 
3254   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3255 
3256   RTCAudioSourceStats expected_audio("SA42", report->timestamp_us());
3257   expected_audio.track_identifier = "LocalAudioTrackID";
3258   expected_audio.kind = "audio";
3259   expected_audio.audio_level = 1.0;  // [0,1]
3260   expected_audio.total_audio_energy = 2.0;
3261   expected_audio.total_samples_duration = 3.0;
3262   expected_audio.echo_return_loss = 42.0;
3263   expected_audio.echo_return_loss_enhancement = 52.0;
3264 
3265   ASSERT_TRUE(report->Get(expected_audio.id()));
3266   EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
3267             expected_audio);
3268 }
3269 
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsCollectedForSenderWithTrack)3270 TEST_F(RTCStatsCollectorTest, RTCVideoSourceStatsCollectedForSenderWithTrack) {
3271   const uint32_t kSsrc = 4;
3272   const int kAttachmentId = 42;
3273   const int kVideoSourceWidth = 12;
3274   const int kVideoSourceHeight = 34;
3275 
3276   cricket::VideoMediaInfo video_media_info;
3277   video_media_info.aggregated_senders.push_back(cricket::VideoSenderInfo());
3278   video_media_info.senders.push_back(cricket::VideoSenderInfo());
3279   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3280   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
3281   video_media_info.senders[0].framerate_input = 29.0;
3282   video_media_info.aggregated_senders[0].local_stats.push_back(
3283       cricket::SsrcSenderInfo());
3284   video_media_info.aggregated_senders[0].local_stats[0].ssrc = kSsrc;
3285   video_media_info.aggregated_senders[0].framerate_input = 29.0;
3286   video_media_info.aggregated_senders[0].frames = 10001;
3287   pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
3288 
3289   auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
3290                                                            kVideoSourceHeight);
3291   auto video_track = FakeVideoTrackForStats::Create(
3292       "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
3293   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3294       cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
3295   EXPECT_CALL(*sender, Stop());
3296   EXPECT_CALL(*sender, SetMediaChannel(_));
3297   pc_->AddSender(sender);
3298 
3299   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3300 
3301   RTCVideoSourceStats expected_video("SV42", report->timestamp_us());
3302   expected_video.track_identifier = "LocalVideoTrackID";
3303   expected_video.kind = "video";
3304   expected_video.width = kVideoSourceWidth;
3305   expected_video.height = kVideoSourceHeight;
3306   expected_video.frames_per_second = 29.0;
3307   expected_video.frames = 10001;
3308 
3309   ASSERT_TRUE(report->Get(expected_video.id()));
3310   EXPECT_EQ(report->Get(expected_video.id())->cast_to<RTCVideoSourceStats>(),
3311             expected_video);
3312 }
3313 
3314 // This test exercises the current behavior and code path, but the correct
3315 // behavior is to report frame rate even if we have no SSRC.
3316 // TODO(hbos): When we know the frame rate even if we have no SSRC, update the
3317 // expectations of this test.
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc)3318 TEST_F(RTCStatsCollectorTest,
3319        RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc) {
3320   // TODO(https://crbug.com/webrtc/8694): When 0 is no longer a magic value for
3321   // "none", update this test.
3322   const uint32_t kNoSsrc = 0;
3323   const int kAttachmentId = 42;
3324   const int kVideoSourceWidth = 12;
3325   const int kVideoSourceHeight = 34;
3326 
3327   cricket::VideoMediaInfo video_media_info;
3328   video_media_info.senders.push_back(cricket::VideoSenderInfo());
3329   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3330   video_media_info.senders[0].framerate_input = 29.0;
3331   pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
3332 
3333   auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
3334                                                            kVideoSourceHeight);
3335   auto video_track = FakeVideoTrackForStats::Create(
3336       "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
3337   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3338       cricket::MEDIA_TYPE_VIDEO, video_track, kNoSsrc, kAttachmentId, {});
3339   EXPECT_CALL(*sender, Stop());
3340   EXPECT_CALL(*sender, SetMediaChannel(_));
3341   pc_->AddSender(sender);
3342 
3343   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3344   ASSERT_TRUE(report->Get("SV42"));
3345   auto video_stats = report->Get("SV42")->cast_to<RTCVideoSourceStats>();
3346   EXPECT_FALSE(video_stats.frames_per_second.is_defined());
3347   EXPECT_FALSE(video_stats.frames.is_defined());
3348 }
3349 
3350 // The track not having a source is not expected to be true in practise, but
3351 // this is true in some tests relying on fakes. This test covers that code path.
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource)3352 TEST_F(RTCStatsCollectorTest,
3353        RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource) {
3354   const uint32_t kSsrc = 4;
3355   const int kAttachmentId = 42;
3356 
3357   cricket::VideoMediaInfo video_media_info;
3358   video_media_info.senders.push_back(cricket::VideoSenderInfo());
3359   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3360   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
3361   video_media_info.senders[0].framerate_input = 29.0;
3362   pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
3363 
3364   auto video_track = FakeVideoTrackForStats::Create(
3365       "LocalVideoTrackID", MediaStreamTrackInterface::kLive,
3366       /*source=*/nullptr);
3367   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3368       cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
3369   EXPECT_CALL(*sender, Stop());
3370   EXPECT_CALL(*sender, SetMediaChannel(_));
3371   pc_->AddSender(sender);
3372 
3373   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3374   ASSERT_TRUE(report->Get("SV42"));
3375   auto video_stats = report->Get("SV42")->cast_to<RTCVideoSourceStats>();
3376   EXPECT_FALSE(video_stats.width.is_defined());
3377   EXPECT_FALSE(video_stats.height.is_defined());
3378 }
3379 
TEST_F(RTCStatsCollectorTest,RTCAudioSourceStatsNotCollectedForSenderWithoutTrack)3380 TEST_F(RTCStatsCollectorTest,
3381        RTCAudioSourceStatsNotCollectedForSenderWithoutTrack) {
3382   const uint32_t kSsrc = 4;
3383   const int kAttachmentId = 42;
3384 
3385   cricket::VoiceMediaInfo voice_media_info;
3386   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
3387   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3388   voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
3389   pc_->AddVoiceChannel("AudioMid", "TransportName", voice_media_info);
3390   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3391       cricket::MEDIA_TYPE_AUDIO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
3392   EXPECT_CALL(*sender, Stop());
3393   EXPECT_CALL(*sender, SetMediaChannel(_));
3394   pc_->AddSender(sender);
3395 
3396   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3397   EXPECT_FALSE(report->Get("SA42"));
3398 }
3399 
3400 // Parameterized tests on cricket::MediaType (audio or video).
3401 class RTCStatsCollectorTestWithParamKind
3402     : public RTCStatsCollectorTest,
3403       public ::testing::WithParamInterface<cricket::MediaType> {
3404  public:
RTCStatsCollectorTestWithParamKind()3405   RTCStatsCollectorTestWithParamKind() : media_type_(GetParam()) {
3406     RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
3407                media_type_ == cricket::MEDIA_TYPE_VIDEO);
3408   }
3409 
MediaTypeCharStr() const3410   std::string MediaTypeCharStr() const {
3411     switch (media_type_) {
3412       case cricket::MEDIA_TYPE_AUDIO:
3413         return "A";
3414       case cricket::MEDIA_TYPE_VIDEO:
3415         return "V";
3416       case cricket::MEDIA_TYPE_DATA:
3417       case cricket::MEDIA_TYPE_UNSUPPORTED:
3418         RTC_DCHECK_NOTREACHED();
3419         return "?";
3420     }
3421   }
3422 
MediaTypeKind() const3423   std::string MediaTypeKind() const {
3424     switch (media_type_) {
3425       case cricket::MEDIA_TYPE_AUDIO:
3426         return "audio";
3427       case cricket::MEDIA_TYPE_VIDEO:
3428         return "video";
3429       case cricket::MEDIA_TYPE_DATA:
3430       case cricket::MEDIA_TYPE_UNSUPPORTED:
3431         RTC_DCHECK_NOTREACHED();
3432         return "";
3433     }
3434   }
3435 
3436   // Adds a sender and channel of the appropriate kind, creating a sender info
3437   // with the report block's `source_ssrc` and report block data.
AddSenderInfoAndMediaChannel(std::string transport_name,const std::vector<ReportBlockData> & report_block_datas,absl::optional<RtpCodecParameters> codec)3438   void AddSenderInfoAndMediaChannel(
3439       std::string transport_name,
3440       const std::vector<ReportBlockData>& report_block_datas,
3441       absl::optional<RtpCodecParameters> codec) {
3442     switch (media_type_) {
3443       case cricket::MEDIA_TYPE_AUDIO: {
3444         cricket::VoiceMediaInfo voice_media_info;
3445         for (const auto& report_block_data : report_block_datas) {
3446           cricket::VoiceSenderInfo sender;
3447           sender.local_stats.push_back(cricket::SsrcSenderInfo());
3448           sender.local_stats[0].ssrc =
3449               report_block_data.report_block().source_ssrc;
3450           if (codec.has_value()) {
3451             sender.codec_payload_type = codec->payload_type;
3452             voice_media_info.send_codecs.insert(
3453                 std::make_pair(codec->payload_type, *codec));
3454           }
3455           sender.report_block_datas.push_back(report_block_data);
3456           voice_media_info.senders.push_back(sender);
3457         }
3458         pc_->AddVoiceChannel("mid", transport_name, voice_media_info);
3459         return;
3460       }
3461       case cricket::MEDIA_TYPE_VIDEO: {
3462         cricket::VideoMediaInfo video_media_info;
3463         for (const auto& report_block_data : report_block_datas) {
3464           cricket::VideoSenderInfo sender;
3465           sender.local_stats.push_back(cricket::SsrcSenderInfo());
3466           sender.local_stats[0].ssrc =
3467               report_block_data.report_block().source_ssrc;
3468           if (codec.has_value()) {
3469             sender.codec_payload_type = codec->payload_type;
3470             video_media_info.send_codecs.insert(
3471                 std::make_pair(codec->payload_type, *codec));
3472           }
3473           sender.report_block_datas.push_back(report_block_data);
3474           video_media_info.aggregated_senders.push_back(sender);
3475           video_media_info.senders.push_back(sender);
3476         }
3477         pc_->AddVideoChannel("mid", transport_name, video_media_info);
3478         return;
3479       }
3480       case cricket::MEDIA_TYPE_DATA:
3481       case cricket::MEDIA_TYPE_UNSUPPORTED:
3482         RTC_DCHECK_NOTREACHED();
3483     }
3484   }
3485 
3486  protected:
3487   cricket::MediaType media_type_;
3488 };
3489 
3490 // Verifies RTCRemoteInboundRtpStreamStats members that don't require
3491 // RTCCodecStats (codecId, jitter) and without setting up an RTCP transport.
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsCollectedFromReportBlock)3492 TEST_P(RTCStatsCollectorTestWithParamKind,
3493        RTCRemoteInboundRtpStreamStatsCollectedFromReportBlock) {
3494   const int64_t kReportBlockTimestampUtcUs = 123456789;
3495   const uint8_t kFractionLost = 12;
3496   const int64_t kRoundTripTimeSample1Ms = 1234;
3497   const double kRoundTripTimeSample1Seconds = 1.234;
3498   const int64_t kRoundTripTimeSample2Ms = 13000;
3499   const double kRoundTripTimeSample2Seconds = 13;
3500 
3501   // The report block's timestamp cannot be from the future, set the fake clock
3502   // to match.
3503   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
3504   auto ssrcs = {12, 13};
3505   std::vector<ReportBlockData> report_block_datas;
3506   for (auto ssrc : ssrcs) {
3507     RTCPReportBlock report_block;
3508     // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
3509     // `source_ssrc`, "SSRC of the RTP packet sender".
3510     report_block.source_ssrc = ssrc;
3511     report_block.packets_lost = 7;
3512     report_block.fraction_lost = kFractionLost;
3513     ReportBlockData report_block_data;
3514     report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3515     report_block_data.AddRoundTripTimeSample(kRoundTripTimeSample1Ms);
3516     // Only the last sample should be exposed as the
3517     // `RTCRemoteInboundRtpStreamStats::round_trip_time`.
3518     report_block_data.AddRoundTripTimeSample(kRoundTripTimeSample2Ms);
3519     report_block_datas.push_back(report_block_data);
3520   }
3521   AddSenderInfoAndMediaChannel("TransportName", report_block_datas,
3522                                absl::nullopt);
3523 
3524   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3525   for (auto ssrc : ssrcs) {
3526     std::string stream_id = "" + std::to_string(ssrc);
3527     RTCRemoteInboundRtpStreamStats expected_remote_inbound_rtp(
3528         "RI" + MediaTypeCharStr() + stream_id, kReportBlockTimestampUtcUs);
3529     expected_remote_inbound_rtp.ssrc = ssrc;
3530     expected_remote_inbound_rtp.fraction_lost =
3531         static_cast<double>(kFractionLost) / (1 << 8);
3532     expected_remote_inbound_rtp.kind = MediaTypeKind();
3533     expected_remote_inbound_rtp.transport_id =
3534         "TTransportName1";  // 1 for RTP (we have no RTCP
3535                             // transport)
3536     expected_remote_inbound_rtp.packets_lost = 7;
3537     expected_remote_inbound_rtp.local_id =
3538         "OTTransportName1" + MediaTypeCharStr() + stream_id;
3539     expected_remote_inbound_rtp.round_trip_time = kRoundTripTimeSample2Seconds;
3540     expected_remote_inbound_rtp.total_round_trip_time =
3541         kRoundTripTimeSample1Seconds + kRoundTripTimeSample2Seconds;
3542     expected_remote_inbound_rtp.round_trip_time_measurements = 2;
3543     // This test does not set up RTCCodecStats, so `codec_id` and `jitter` are
3544     // expected to be missing. These are tested separately.
3545 
3546     ASSERT_TRUE(report->Get(expected_remote_inbound_rtp.id()));
3547     EXPECT_EQ(report->Get(expected_remote_inbound_rtp.id())
3548                   ->cast_to<RTCRemoteInboundRtpStreamStats>(),
3549               expected_remote_inbound_rtp);
3550     EXPECT_TRUE(report->Get(*expected_remote_inbound_rtp.transport_id));
3551     ASSERT_TRUE(report->Get(*expected_remote_inbound_rtp.local_id));
3552     // Lookup works in both directions.
3553     EXPECT_EQ(*report->Get(*expected_remote_inbound_rtp.local_id)
3554                    ->cast_to<RTCOutboundRTPStreamStats>()
3555                    .remote_id,
3556               expected_remote_inbound_rtp.id());
3557   }
3558 }
3559 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsRttMissingBeforeMeasurement)3560 TEST_P(RTCStatsCollectorTestWithParamKind,
3561        RTCRemoteInboundRtpStreamStatsRttMissingBeforeMeasurement) {
3562   constexpr int64_t kReportBlockTimestampUtcUs = 123456789;
3563 
3564   RTCPReportBlock report_block;
3565   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
3566   // `source_ssrc`, "SSRC of the RTP packet sender".
3567   report_block.source_ssrc = 12;
3568   ReportBlockData report_block_data;  // AddRoundTripTimeSample() not called.
3569   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3570 
3571   AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
3572                                absl::nullopt);
3573 
3574   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3575 
3576   std::string remote_inbound_rtp_id = "RI" + MediaTypeCharStr() + "12";
3577   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3578   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3579                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
3580 
3581   EXPECT_TRUE(remote_inbound_rtp.round_trip_time_measurements.is_defined());
3582   EXPECT_EQ(0, *remote_inbound_rtp.round_trip_time_measurements);
3583   EXPECT_FALSE(remote_inbound_rtp.round_trip_time.is_defined());
3584 }
3585 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithTimestampFromReportBlock)3586 TEST_P(RTCStatsCollectorTestWithParamKind,
3587        RTCRemoteInboundRtpStreamStatsWithTimestampFromReportBlock) {
3588   const int64_t kReportBlockTimestampUtcUs = 123456789;
3589   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
3590 
3591   RTCPReportBlock report_block;
3592   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
3593   // `source_ssrc`, "SSRC of the RTP packet sender".
3594   report_block.source_ssrc = 12;
3595   ReportBlockData report_block_data;
3596   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3597 
3598   AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
3599                                absl::nullopt);
3600 
3601   // Advance time, it should be OK to have fresher reports than report blocks.
3602   fake_clock_.AdvanceTime(TimeDelta::Micros(1234));
3603 
3604   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3605 
3606   std::string remote_inbound_rtp_id = "RI" + MediaTypeCharStr() + "12";
3607   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3608   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3609                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
3610 
3611   // Even though the report time is different, the remote-inbound-rtp timestamp
3612   // is of the time that the report block was received.
3613   EXPECT_EQ(kReportBlockTimestampUtcUs + 1234, report->timestamp_us());
3614   EXPECT_EQ(kReportBlockTimestampUtcUs, remote_inbound_rtp.timestamp_us());
3615 }
3616 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithCodecBasedMembers)3617 TEST_P(RTCStatsCollectorTestWithParamKind,
3618        RTCRemoteInboundRtpStreamStatsWithCodecBasedMembers) {
3619   const int64_t kReportBlockTimestampUtcUs = 123456789;
3620   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
3621 
3622   RTCPReportBlock report_block;
3623   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
3624   // `source_ssrc`, "SSRC of the RTP packet sender".
3625   report_block.source_ssrc = 12;
3626   report_block.jitter = 5000;
3627   ReportBlockData report_block_data;
3628   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3629 
3630   RtpCodecParameters codec;
3631   codec.payload_type = 3;
3632   codec.kind = media_type_;
3633   codec.clock_rate = 1000;
3634 
3635   AddSenderInfoAndMediaChannel("TransportName", {report_block_data}, codec);
3636 
3637   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3638 
3639   std::string remote_inbound_rtp_id = "RI" + MediaTypeCharStr() + "12";
3640   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3641   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3642                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
3643 
3644   EXPECT_TRUE(remote_inbound_rtp.codec_id.is_defined());
3645   EXPECT_TRUE(report->Get(*remote_inbound_rtp.codec_id));
3646 
3647   EXPECT_TRUE(remote_inbound_rtp.jitter.is_defined());
3648   // The jitter (in seconds) is the report block's jitter divided by the codec's
3649   // clock rate.
3650   EXPECT_EQ(5.0, *remote_inbound_rtp.jitter);
3651 }
3652 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithRtcpTransport)3653 TEST_P(RTCStatsCollectorTestWithParamKind,
3654        RTCRemoteInboundRtpStreamStatsWithRtcpTransport) {
3655   const int64_t kReportBlockTimestampUtcUs = 123456789;
3656   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
3657 
3658   RTCPReportBlock report_block;
3659   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
3660   // `source_ssrc`, "SSRC of the RTP packet sender".
3661   report_block.source_ssrc = 12;
3662   ReportBlockData report_block_data;
3663   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
3664 
3665   cricket::TransportChannelStats rtp_transport_channel_stats;
3666   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
3667   rtp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
3668   cricket::TransportChannelStats rtcp_transport_channel_stats;
3669   rtcp_transport_channel_stats.component =
3670       cricket::ICE_CANDIDATE_COMPONENT_RTCP;
3671   rtcp_transport_channel_stats.dtls_state = DtlsTransportState::kNew;
3672   pc_->SetTransportStats("TransportName", {rtp_transport_channel_stats,
3673                                            rtcp_transport_channel_stats});
3674   AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
3675                                absl::nullopt);
3676 
3677   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3678 
3679   std::string remote_inbound_rtp_id = "RI" + MediaTypeCharStr() + "12";
3680   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
3681   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
3682                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
3683 
3684   EXPECT_TRUE(remote_inbound_rtp.transport_id.is_defined());
3685   EXPECT_EQ("TTransportName2",  // 2 for RTCP
3686             *remote_inbound_rtp.transport_id);
3687   EXPECT_TRUE(report->Get(*remote_inbound_rtp.transport_id));
3688 }
3689 
3690 INSTANTIATE_TEST_SUITE_P(All,
3691                          RTCStatsCollectorTestWithParamKind,
3692                          ::testing::Values(cricket::MEDIA_TYPE_AUDIO,    // "/0"
3693                                            cricket::MEDIA_TYPE_VIDEO));  // "/1"
3694 
3695 // Checks that no remote outbound stats are collected if not available in
3696 // `VoiceMediaInfo`.
TEST_F(RTCStatsCollectorTest,RTCRemoteOutboundRtpAudioStreamStatsNotCollected)3697 TEST_F(RTCStatsCollectorTest,
3698        RTCRemoteOutboundRtpAudioStreamStatsNotCollected) {
3699   ExampleStatsGraph graph =
3700       SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/false);
3701   EXPECT_FALSE(graph.full_report->Get(graph.remote_outbound_rtp_id));
3702   // Also check that no other remote outbound report is created (in case the
3703   // expected ID is incorrect).
3704   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3705   ASSERT_NE(report->begin(), report->end())
3706       << "No reports have been generated.";
3707   for (const auto& stats : *report) {
3708     SCOPED_TRACE(stats.id());
3709     EXPECT_NE(stats.type(), RTCRemoteOutboundRtpStreamStats::kType);
3710   }
3711 }
3712 
3713 // Checks that the remote outbound stats are collected when available in
3714 // `VoiceMediaInfo`.
TEST_F(RTCStatsCollectorTest,RTCRemoteOutboundRtpAudioStreamStatsCollected)3715 TEST_F(RTCStatsCollectorTest, RTCRemoteOutboundRtpAudioStreamStatsCollected) {
3716   ExampleStatsGraph graph =
3717       SetupExampleStatsVoiceGraph(/*add_remote_outbound_stats=*/true);
3718   ASSERT_TRUE(graph.full_report->Get(graph.remote_outbound_rtp_id));
3719   const auto& remote_outbound_rtp =
3720       graph.full_report->Get(graph.remote_outbound_rtp_id)
3721           ->cast_to<RTCRemoteOutboundRtpStreamStats>();
3722   EXPECT_EQ(remote_outbound_rtp.timestamp_us(),
3723             kRemoteOutboundStatsTimestampMs * rtc::kNumMicrosecsPerMillisec);
3724   EXPECT_FLOAT_EQ(*remote_outbound_rtp.remote_timestamp,
3725                   static_cast<double>(kRemoteOutboundStatsRemoteTimestampMs));
3726   EXPECT_EQ(*remote_outbound_rtp.packets_sent, kRemoteOutboundStatsPacketsSent);
3727   EXPECT_EQ(*remote_outbound_rtp.bytes_sent, kRemoteOutboundStatsBytesSent);
3728   EXPECT_EQ(*remote_outbound_rtp.reports_sent,
3729             kRemoteOutboundStatsReportsCount);
3730 }
3731 
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsNotCollectedForSenderWithoutTrack)3732 TEST_F(RTCStatsCollectorTest,
3733        RTCVideoSourceStatsNotCollectedForSenderWithoutTrack) {
3734   const uint32_t kSsrc = 4;
3735   const int kAttachmentId = 42;
3736 
3737   cricket::VideoMediaInfo video_media_info;
3738   video_media_info.senders.push_back(cricket::VideoSenderInfo());
3739   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
3740   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
3741   video_media_info.senders[0].framerate_input = 29.0;
3742   pc_->AddVideoChannel("VideoMid", "TransportName", video_media_info);
3743 
3744   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
3745       cricket::MEDIA_TYPE_VIDEO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
3746   EXPECT_CALL(*sender, Stop());
3747   EXPECT_CALL(*sender, SetMediaChannel(_));
3748   pc_->AddSender(sender);
3749 
3750   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3751   EXPECT_FALSE(report->Get("SV42"));
3752 }
3753 
3754 // Test collecting echo return loss stats from the audio processor attached to
3755 // the track, rather than the voice sender info.
TEST_F(RTCStatsCollectorTest,CollectEchoReturnLossFromTrackAudioProcessor)3756 TEST_F(RTCStatsCollectorTest, CollectEchoReturnLossFromTrackAudioProcessor) {
3757   rtc::scoped_refptr<MediaStream> local_stream =
3758       MediaStream::Create("LocalStreamId");
3759   pc_->mutable_local_streams()->AddStream(local_stream);
3760 
3761   // Local audio track
3762   rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
3763       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
3764                       MediaStreamTrackInterface::kEnded,
3765                       /*create_fake_audio_processor=*/true);
3766   local_stream->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(
3767       static_cast<AudioTrackInterface*>(local_audio_track.get())));
3768 
3769   cricket::VoiceSenderInfo voice_sender_info_ssrc1;
3770   voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
3771   voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
3772 
3773   stats_->CreateMockRtpSendersReceiversAndChannels(
3774       {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
3775       {}, {}, {local_stream->id()}, {});
3776 
3777   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3778 
3779   DEPRECATED_RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
3780       IdForType<DEPRECATED_RTCMediaStreamTrackStats>(report.get()),
3781       report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
3782   expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
3783   expected_local_audio_track_ssrc1.media_source_id =
3784       "SA11";  // Attachment ID = SSRC + 10
3785   expected_local_audio_track_ssrc1.remote_source = false;
3786   expected_local_audio_track_ssrc1.ended = true;
3787   expected_local_audio_track_ssrc1.detached = false;
3788   expected_local_audio_track_ssrc1.echo_return_loss = 2.0;
3789   expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 3.0;
3790   ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
3791       << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
3792       << report->ToJson();
3793   EXPECT_EQ(expected_local_audio_track_ssrc1,
3794             report->Get(expected_local_audio_track_ssrc1.id())
3795                 ->cast_to<DEPRECATED_RTCMediaStreamTrackStats>());
3796 
3797   RTCAudioSourceStats expected_audio("SA11", report->timestamp_us());
3798   expected_audio.track_identifier = "LocalAudioTrackID";
3799   expected_audio.kind = "audio";
3800   expected_audio.audio_level = 0;
3801   expected_audio.total_audio_energy = 0;
3802   expected_audio.total_samples_duration = 0;
3803   expected_audio.echo_return_loss = 2.0;
3804   expected_audio.echo_return_loss_enhancement = 3.0;
3805 
3806   ASSERT_TRUE(report->Get(expected_audio.id()));
3807   EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
3808             expected_audio);
3809 }
3810 
TEST_F(RTCStatsCollectorTest,GetStatsWithSenderSelector)3811 TEST_F(RTCStatsCollectorTest, GetStatsWithSenderSelector) {
3812   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3813   // Expected stats graph when filtered by sender:
3814   //
3815   //  +--- track (sender)
3816   //  |             ^
3817   //  |             |
3818   //  | +--------- outbound-rtp
3819   //  | |           |        |
3820   //  | |           v        v
3821   //  | |  codec (send)     transport
3822   //  v v
3823   //  media-source
3824   rtc::scoped_refptr<const RTCStatsReport> sender_report =
3825       stats_->GetStatsReportWithSenderSelector(graph.sender);
3826   EXPECT_TRUE(sender_report);
3827   EXPECT_EQ(sender_report->timestamp_us(), graph.full_report->timestamp_us());
3828   EXPECT_EQ(sender_report->size(), 5u);
3829   EXPECT_TRUE(sender_report->Get(graph.send_codec_id));
3830   EXPECT_FALSE(sender_report->Get(graph.recv_codec_id));
3831   EXPECT_TRUE(sender_report->Get(graph.outbound_rtp_id));
3832   EXPECT_FALSE(sender_report->Get(graph.inbound_rtp_id));
3833   EXPECT_TRUE(sender_report->Get(graph.transport_id));
3834   EXPECT_TRUE(sender_report->Get(graph.sender_track_id));
3835   EXPECT_FALSE(sender_report->Get(graph.receiver_track_id));
3836   EXPECT_FALSE(sender_report->Get(graph.remote_stream_id));
3837   EXPECT_FALSE(sender_report->Get(graph.peer_connection_id));
3838   EXPECT_TRUE(sender_report->Get(graph.media_source_id));
3839 }
3840 
TEST_F(RTCStatsCollectorTest,GetStatsWithReceiverSelector)3841 TEST_F(RTCStatsCollectorTest, GetStatsWithReceiverSelector) {
3842   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3843   // Expected stats graph when filtered by receiver:
3844   //
3845   //                                                       track (receiver)
3846   //                                                         ^
3847   //                                                         |
3848   //                              inbound-rtp ---------------+
3849   //                               |       |
3850   //                               v       v
3851   //                        transport     codec (recv)
3852   rtc::scoped_refptr<const RTCStatsReport> receiver_report =
3853       stats_->GetStatsReportWithReceiverSelector(graph.receiver);
3854   EXPECT_TRUE(receiver_report);
3855   EXPECT_EQ(receiver_report->size(), 4u);
3856   EXPECT_EQ(receiver_report->timestamp_us(), graph.full_report->timestamp_us());
3857   EXPECT_FALSE(receiver_report->Get(graph.send_codec_id));
3858   EXPECT_TRUE(receiver_report->Get(graph.recv_codec_id));
3859   EXPECT_FALSE(receiver_report->Get(graph.outbound_rtp_id));
3860   EXPECT_TRUE(receiver_report->Get(graph.inbound_rtp_id));
3861   EXPECT_TRUE(receiver_report->Get(graph.transport_id));
3862   EXPECT_FALSE(receiver_report->Get(graph.sender_track_id));
3863   EXPECT_TRUE(receiver_report->Get(graph.receiver_track_id));
3864   EXPECT_FALSE(receiver_report->Get(graph.remote_stream_id));
3865   EXPECT_FALSE(receiver_report->Get(graph.peer_connection_id));
3866   EXPECT_FALSE(receiver_report->Get(graph.media_source_id));
3867 }
3868 
TEST_F(RTCStatsCollectorTest,GetStatsWithNullSenderSelector)3869 TEST_F(RTCStatsCollectorTest, GetStatsWithNullSenderSelector) {
3870   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3871   rtc::scoped_refptr<const RTCStatsReport> empty_report =
3872       stats_->GetStatsReportWithSenderSelector(nullptr);
3873   EXPECT_TRUE(empty_report);
3874   EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
3875   EXPECT_EQ(empty_report->size(), 0u);
3876 }
3877 
TEST_F(RTCStatsCollectorTest,GetStatsWithNullReceiverSelector)3878 TEST_F(RTCStatsCollectorTest, GetStatsWithNullReceiverSelector) {
3879   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
3880   rtc::scoped_refptr<const RTCStatsReport> empty_report =
3881       stats_->GetStatsReportWithReceiverSelector(nullptr);
3882   EXPECT_TRUE(empty_report);
3883   EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
3884   EXPECT_EQ(empty_report->size(), 0u);
3885 }
3886 
3887 // When the PC has not had SetLocalDescription done, tracks all have
3888 // SSRC 0, meaning "unconnected".
3889 // In this state, we report on track stats, but not RTP stats.
TEST_F(RTCStatsCollectorTest,StatsReportedOnZeroSsrc)3890 TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
3891   rtc::scoped_refptr<MediaStreamTrackInterface> track =
3892       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
3893                       MediaStreamTrackInterface::kLive);
3894   rtc::scoped_refptr<MockRtpSenderInternal> sender =
3895       CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 0, 49, {});
3896   EXPECT_CALL(*sender, Stop());
3897   pc_->AddSender(sender);
3898 
3899   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3900 
3901   std::vector<const DEPRECATED_RTCMediaStreamTrackStats*> track_stats =
3902       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
3903   EXPECT_EQ(1U, track_stats.size());
3904 
3905   std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
3906       report->GetStatsOfType<RTCRTPStreamStats>();
3907   EXPECT_EQ(0U, rtp_stream_stats.size());
3908 }
3909 
TEST_F(RTCStatsCollectorTest,DoNotCrashOnSsrcChange)3910 TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
3911   rtc::scoped_refptr<MediaStreamTrackInterface> track =
3912       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
3913                       MediaStreamTrackInterface::kLive);
3914   rtc::scoped_refptr<MockRtpSenderInternal> sender =
3915       CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 4711, 49, {});
3916   EXPECT_CALL(*sender, Stop());
3917   pc_->AddSender(sender);
3918 
3919   // We do not generate any matching voice_sender_info stats.
3920   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
3921 
3922   std::vector<const DEPRECATED_RTCMediaStreamTrackStats*> track_stats =
3923       report->GetStatsOfType<DEPRECATED_RTCMediaStreamTrackStats>();
3924   EXPECT_EQ(1U, track_stats.size());
3925 }
3926 
3927 // Used for test below, to test calling GetStatsReport during a callback.
3928 class RecursiveCallback : public RTCStatsCollectorCallback {
3929  public:
RecursiveCallback(RTCStatsCollectorWrapper * stats)3930   explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
3931 
OnStatsDelivered(const rtc::scoped_refptr<const RTCStatsReport> & report)3932   void OnStatsDelivered(
3933       const rtc::scoped_refptr<const RTCStatsReport>& report) override {
3934     stats_->GetStatsReport();
3935     called_ = true;
3936   }
3937 
called() const3938   bool called() const { return called_; }
3939 
3940  private:
3941   RTCStatsCollectorWrapper* stats_;
3942   bool called_ = false;
3943 };
3944 
3945 // Test that nothing bad happens if a callback causes GetStatsReport to be
3946 // called again recursively. Regression test for crbug.com/webrtc/8973.
TEST_F(RTCStatsCollectorTest,DoNotCrashWhenGetStatsCalledDuringCallback)3947 TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
3948   auto callback1 = rtc::make_ref_counted<RecursiveCallback>(stats_.get());
3949   auto callback2 = rtc::make_ref_counted<RecursiveCallback>(stats_.get());
3950   stats_->stats_collector()->GetStatsReport(callback1);
3951   stats_->stats_collector()->GetStatsReport(callback2);
3952   EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
3953   EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
3954 }
3955 
3956 class RTCTestStats : public RTCStats {
3957  public:
3958   WEBRTC_RTCSTATS_DECL();
3959 
RTCTestStats(const std::string & id,int64_t timestamp_us)3960   RTCTestStats(const std::string& id, int64_t timestamp_us)
3961       : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
3962 
3963   RTCStatsMember<int32_t> dummy_stat;
3964 };
3965 
3966 WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat)
3967 
3968 // Overrides the stats collection to verify thread usage and that the resulting
3969 // partial reports are merged.
3970 class FakeRTCStatsCollector : public RTCStatsCollector,
3971                               public RTCStatsCollectorCallback {
3972  public:
Create(PeerConnectionInternal * pc,int64_t cache_lifetime_us)3973   static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
3974       PeerConnectionInternal* pc,
3975       int64_t cache_lifetime_us) {
3976     return rtc::scoped_refptr<FakeRTCStatsCollector>(
3977         new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
3978                                                          cache_lifetime_us));
3979   }
3980 
3981   // Since FakeRTCStatsCollector inherits twice from RefCountInterface, once via
3982   // RTCStatsCollector and once via RTCStatsCollectorCallback, scoped_refptr
3983   // will get confused about which  AddRef()/Release() methods to call.
3984   // So to remove all doubt, we declare them here again in the class that we
3985   // give to scoped_refptr.
3986   // Satisfying the implementation of these methods and associating them with a
3987   // reference counter, will be done by RefCountedObject.
3988   virtual void AddRef() const = 0;
3989   virtual rtc::RefCountReleaseStatus Release() const = 0;
3990 
3991   // RTCStatsCollectorCallback implementation.
OnStatsDelivered(const rtc::scoped_refptr<const RTCStatsReport> & report)3992   void OnStatsDelivered(
3993       const rtc::scoped_refptr<const RTCStatsReport>& report) override {
3994     EXPECT_TRUE(signaling_thread_->IsCurrent());
3995     MutexLock lock(&lock_);
3996     delivered_report_ = report;
3997   }
3998 
VerifyThreadUsageAndResultsMerging()3999   void VerifyThreadUsageAndResultsMerging() {
4000     GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
4001     EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
4002   }
4003 
HasVerifiedResults()4004   bool HasVerifiedResults() {
4005     EXPECT_TRUE(signaling_thread_->IsCurrent());
4006     MutexLock lock(&lock_);
4007     if (!delivered_report_)
4008       return false;
4009     EXPECT_EQ(produced_on_signaling_thread_, 1);
4010     EXPECT_EQ(produced_on_network_thread_, 1);
4011 
4012     EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
4013     EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
4014 
4015     produced_on_signaling_thread_ = 0;
4016     produced_on_network_thread_ = 0;
4017     delivered_report_ = nullptr;
4018     return true;
4019   }
4020 
4021  protected:
FakeRTCStatsCollector(PeerConnectionInternal * pc,int64_t cache_lifetime)4022   FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
4023       : RTCStatsCollector(pc, cache_lifetime),
4024         signaling_thread_(pc->signaling_thread()),
4025         worker_thread_(pc->worker_thread()),
4026         network_thread_(pc->network_thread()) {}
4027 
ProducePartialResultsOnSignalingThreadImpl(int64_t timestamp_us,RTCStatsReport * partial_report)4028   void ProducePartialResultsOnSignalingThreadImpl(
4029       int64_t timestamp_us,
4030       RTCStatsReport* partial_report) override {
4031     EXPECT_TRUE(signaling_thread_->IsCurrent());
4032     {
4033       MutexLock lock(&lock_);
4034       EXPECT_FALSE(delivered_report_);
4035       ++produced_on_signaling_thread_;
4036     }
4037 
4038     partial_report->AddStats(std::unique_ptr<const RTCStats>(
4039         new RTCTestStats("SignalingThreadStats", timestamp_us)));
4040   }
ProducePartialResultsOnNetworkThreadImpl(int64_t timestamp_us,const std::map<std::string,cricket::TransportStats> & transport_stats_by_name,const std::map<std::string,CertificateStatsPair> & transport_cert_stats,RTCStatsReport * partial_report)4041   void ProducePartialResultsOnNetworkThreadImpl(
4042       int64_t timestamp_us,
4043       const std::map<std::string, cricket::TransportStats>&
4044           transport_stats_by_name,
4045       const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
4046       RTCStatsReport* partial_report) override {
4047     EXPECT_TRUE(network_thread_->IsCurrent());
4048     {
4049       MutexLock lock(&lock_);
4050       EXPECT_FALSE(delivered_report_);
4051       ++produced_on_network_thread_;
4052     }
4053 
4054     partial_report->AddStats(std::unique_ptr<const RTCStats>(
4055         new RTCTestStats("NetworkThreadStats", timestamp_us)));
4056   }
4057 
4058  private:
4059   rtc::Thread* const signaling_thread_;
4060   rtc::Thread* const worker_thread_;
4061   rtc::Thread* const network_thread_;
4062 
4063   Mutex lock_;
4064   rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
4065   int produced_on_signaling_thread_ = 0;
4066   int produced_on_network_thread_ = 0;
4067 };
4068 
TEST(RTCStatsCollectorTestWithFakeCollector,ThreadUsageAndResultsMerging)4069 TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
4070   rtc::AutoThread main_thread_;
4071   auto pc = rtc::make_ref_counted<FakePeerConnectionForStats>();
4072   rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
4073       FakeRTCStatsCollector::Create(pc.get(),
4074                                     50 * rtc::kNumMicrosecsPerMillisec));
4075   stats_collector->VerifyThreadUsageAndResultsMerging();
4076 }
4077 
4078 }  // namespace
4079 
4080 }  // namespace webrtc
4081