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 <ctype.h>
14 
15 #include <algorithm>
16 #include <initializer_list>
17 #include <memory>
18 #include <ostream>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/strings/str_replace.h"
25 #include "api/media_stream_track.h"
26 #include "api/rtp_parameters.h"
27 #include "api/stats/rtc_stats_report.h"
28 #include "api/stats/rtcstats_objects.h"
29 #include "api/units/time_delta.h"
30 #include "modules/rtp_rtcp/include/report_block_data.h"
31 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
32 #include "p2p/base/p2p_constants.h"
33 #include "p2p/base/port.h"
34 #include "pc/media_stream.h"
35 #include "pc/test/fake_data_channel_provider.h"
36 #include "pc/test/fake_peer_connection_for_stats.h"
37 #include "pc/test/mock_data_channel.h"
38 #include "pc/test/mock_rtp_receiver_internal.h"
39 #include "pc/test/mock_rtp_sender_internal.h"
40 #include "pc/test/rtc_stats_obtainer.h"
41 #include "rtc_base/checks.h"
42 #include "rtc_base/fake_clock.h"
43 #include "rtc_base/fake_ssl_identity.h"
44 #include "rtc_base/gunit.h"
45 #include "rtc_base/logging.h"
46 #include "rtc_base/strings/json.h"
47 #include "rtc_base/synchronization/mutex.h"
48 #include "rtc_base/time_utils.h"
49 
50 using ::testing::AtLeast;
51 using ::testing::Invoke;
52 using ::testing::Return;
53 
54 namespace webrtc {
55 
56 // These are used by gtest code, such as if |EXPECT_EQ| fails.
PrintTo(const RTCCertificateStats & stats,::std::ostream * os)57 void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
58   *os << stats.ToJson();
59 }
60 
PrintTo(const RTCCodecStats & stats,::std::ostream * os)61 void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
62   *os << stats.ToJson();
63 }
64 
PrintTo(const RTCDataChannelStats & stats,::std::ostream * os)65 void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
66   *os << stats.ToJson();
67 }
68 
PrintTo(const RTCIceCandidatePairStats & stats,::std::ostream * os)69 void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
70   *os << stats.ToJson();
71 }
72 
PrintTo(const RTCLocalIceCandidateStats & stats,::std::ostream * os)73 void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
74   *os << stats.ToJson();
75 }
76 
PrintTo(const RTCRemoteIceCandidateStats & stats,::std::ostream * os)77 void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
78   *os << stats.ToJson();
79 }
80 
PrintTo(const RTCPeerConnectionStats & stats,::std::ostream * os)81 void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
82   *os << stats.ToJson();
83 }
84 
PrintTo(const RTCMediaStreamStats & stats,::std::ostream * os)85 void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
86   *os << stats.ToJson();
87 }
88 
PrintTo(const RTCMediaStreamTrackStats & stats,::std::ostream * os)89 void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
90   *os << stats.ToJson();
91 }
92 
PrintTo(const RTCInboundRTPStreamStats & stats,::std::ostream * os)93 void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
94   *os << stats.ToJson();
95 }
96 
PrintTo(const RTCOutboundRTPStreamStats & stats,::std::ostream * os)97 void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
98   *os << stats.ToJson();
99 }
100 
PrintTo(const RTCRemoteInboundRtpStreamStats & stats,::std::ostream * os)101 void PrintTo(const RTCRemoteInboundRtpStreamStats& stats, ::std::ostream* os) {
102   *os << stats.ToJson();
103 }
104 
PrintTo(const RTCAudioSourceStats & stats,::std::ostream * os)105 void PrintTo(const RTCAudioSourceStats& stats, ::std::ostream* os) {
106   *os << stats.ToJson();
107 }
108 
PrintTo(const RTCVideoSourceStats & stats,::std::ostream * os)109 void PrintTo(const RTCVideoSourceStats& stats, ::std::ostream* os) {
110   *os << stats.ToJson();
111 }
112 
PrintTo(const RTCTransportStats & stats,::std::ostream * os)113 void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
114   *os << stats.ToJson();
115 }
116 
117 namespace {
118 
119 const int64_t kGetStatsReportTimeoutMs = 1000;
120 
121 struct CertificateInfo {
122   rtc::scoped_refptr<rtc::RTCCertificate> certificate;
123   std::vector<std::string> ders;
124   std::vector<std::string> pems;
125   std::vector<std::string> fingerprints;
126 };
127 
128 // Return the ID for an object of the given type in a report.
129 // The object must be present and be unique.
130 template <typename T>
IdForType(const RTCStatsReport * report)131 std::string IdForType(const RTCStatsReport* report) {
132   auto stats_of_my_type = report->RTCStatsReport::GetStatsOfType<T>();
133   // We cannot use ASSERT here, since we're within a function.
134   EXPECT_EQ(1U, stats_of_my_type.size())
135       << "Unexpected number of stats of this type";
136   if (stats_of_my_type.size() == 1) {
137     return stats_of_my_type[0]->id();
138   } else {
139     // Return something that is not going to be a valid stas ID.
140     return "Type not found";
141   }
142 }
143 
CreateFakeCertificateAndInfoFromDers(const std::vector<std::string> & ders)144 std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
145     const std::vector<std::string>& ders) {
146   RTC_CHECK(!ders.empty());
147   std::unique_ptr<CertificateInfo> info(new CertificateInfo());
148   info->ders = ders;
149   for (const std::string& der : ders) {
150     info->pems.push_back(rtc::SSLIdentity::DerToPem(
151         "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
152         der.length()));
153   }
154   info->certificate =
155       rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
156           new rtc::FakeSSLIdentity(info->pems)));
157   // Strip header/footer and newline characters of PEM strings.
158   for (size_t i = 0; i < info->pems.size(); ++i) {
159     absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
160                          {"-----END CERTIFICATE-----", ""},
161                          {"\n", ""}},
162                         &info->pems[i]);
163   }
164   // Fingerprints for the whole certificate chain, starting with leaf
165   // certificate.
166   const rtc::SSLCertChain& chain = info->certificate->GetSSLCertificateChain();
167   std::unique_ptr<rtc::SSLFingerprint> fp;
168   for (size_t i = 0; i < chain.GetSize(); i++) {
169     fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
170     EXPECT_TRUE(fp);
171     info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
172   }
173   EXPECT_EQ(info->ders.size(), info->fingerprints.size());
174   return info;
175 }
176 
CreateFakeCandidate(const std::string & hostname,int port,const std::string & protocol,const rtc::AdapterType adapter_type,const std::string & candidate_type,uint32_t priority)177 std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
178     const std::string& hostname,
179     int port,
180     const std::string& protocol,
181     const rtc::AdapterType adapter_type,
182     const std::string& candidate_type,
183     uint32_t priority) {
184   std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
185   candidate->set_address(rtc::SocketAddress(hostname, port));
186   candidate->set_protocol(protocol);
187   candidate->set_network_type(adapter_type);
188   candidate->set_type(candidate_type);
189   candidate->set_priority(priority);
190   return candidate;
191 }
192 
193 class FakeAudioTrackForStats : public MediaStreamTrack<AudioTrackInterface> {
194  public:
Create(const std::string & id,MediaStreamTrackInterface::TrackState state)195   static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
196       const std::string& id,
197       MediaStreamTrackInterface::TrackState state) {
198     rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
199         new rtc::RefCountedObject<FakeAudioTrackForStats>(id));
200     audio_track_stats->set_state(state);
201     return audio_track_stats;
202   }
203 
FakeAudioTrackForStats(const std::string & id)204   explicit FakeAudioTrackForStats(const std::string& id)
205       : MediaStreamTrack<AudioTrackInterface>(id) {}
206 
kind() const207   std::string kind() const override {
208     return MediaStreamTrackInterface::kAudioKind;
209   }
GetSource() const210   webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
AddSink(webrtc::AudioTrackSinkInterface * sink)211   void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
RemoveSink(webrtc::AudioTrackSinkInterface * sink)212   void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)213   bool GetSignalLevel(int* level) override { return false; }
GetAudioProcessor()214   rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
215     return nullptr;
216   }
217 };
218 
219 class FakeVideoTrackSourceForStats : public VideoTrackSourceInterface {
220  public:
Create(int input_width,int input_height)221   static rtc::scoped_refptr<FakeVideoTrackSourceForStats> Create(
222       int input_width,
223       int input_height) {
224     return rtc::scoped_refptr<FakeVideoTrackSourceForStats>(
225         new rtc::RefCountedObject<FakeVideoTrackSourceForStats>(input_width,
226                                                                 input_height));
227   }
228 
FakeVideoTrackSourceForStats(int input_width,int input_height)229   FakeVideoTrackSourceForStats(int input_width, int input_height)
230       : input_width_(input_width), input_height_(input_height) {}
~FakeVideoTrackSourceForStats()231   ~FakeVideoTrackSourceForStats() override {}
232 
233   // VideoTrackSourceInterface
is_screencast() const234   bool is_screencast() const override { return false; }
needs_denoising() const235   absl::optional<bool> needs_denoising() const override { return false; }
GetStats(VideoTrackSourceInterface::Stats * stats)236   bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
237     stats->input_width = input_width_;
238     stats->input_height = input_height_;
239     return true;
240   }
241   // MediaSourceInterface (part of VideoTrackSourceInterface)
state() const242   MediaSourceInterface::SourceState state() const override {
243     return MediaSourceInterface::SourceState::kLive;
244   }
remote() const245   bool remote() const override { return false; }
246   // NotifierInterface (part of MediaSourceInterface)
RegisterObserver(ObserverInterface * observer)247   void RegisterObserver(ObserverInterface* observer) override {}
UnregisterObserver(ObserverInterface * observer)248   void UnregisterObserver(ObserverInterface* observer) override {}
249   // rtc::VideoSourceInterface<VideoFrame> (part of VideoTrackSourceInterface)
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)250   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
251                        const rtc::VideoSinkWants& wants) override {}
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)252   void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
SupportsEncodedOutput() const253   bool SupportsEncodedOutput() const override { return false; }
GenerateKeyFrame()254   void GenerateKeyFrame() override {}
AddEncodedSink(rtc::VideoSinkInterface<RecordableEncodedFrame> * sink)255   void AddEncodedSink(
256       rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
RemoveEncodedSink(rtc::VideoSinkInterface<RecordableEncodedFrame> * sink)257   void RemoveEncodedSink(
258       rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) override {}
259 
260  private:
261   int input_width_;
262   int input_height_;
263 };
264 
265 class FakeVideoTrackForStats : public MediaStreamTrack<VideoTrackInterface> {
266  public:
Create(const std::string & id,MediaStreamTrackInterface::TrackState state,rtc::scoped_refptr<VideoTrackSourceInterface> source)267   static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
268       const std::string& id,
269       MediaStreamTrackInterface::TrackState state,
270       rtc::scoped_refptr<VideoTrackSourceInterface> source) {
271     rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
272         new rtc::RefCountedObject<FakeVideoTrackForStats>(id,
273                                                           std::move(source)));
274     video_track->set_state(state);
275     return video_track;
276   }
277 
FakeVideoTrackForStats(const std::string & id,rtc::scoped_refptr<VideoTrackSourceInterface> source)278   FakeVideoTrackForStats(const std::string& id,
279                          rtc::scoped_refptr<VideoTrackSourceInterface> source)
280       : MediaStreamTrack<VideoTrackInterface>(id), source_(source) {}
281 
kind() const282   std::string kind() const override {
283     return MediaStreamTrackInterface::kVideoKind;
284   }
285 
AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame> * sink,const rtc::VideoSinkWants & wants)286   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
287                        const rtc::VideoSinkWants& wants) override {}
RemoveSink(rtc::VideoSinkInterface<VideoFrame> * sink)288   void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
289 
GetSource() const290   VideoTrackSourceInterface* GetSource() const override {
291     return source_.get();
292   }
293 
294  private:
295   rtc::scoped_refptr<VideoTrackSourceInterface> source_;
296 };
297 
CreateFakeTrack(cricket::MediaType media_type,const std::string & track_id,MediaStreamTrackInterface::TrackState track_state)298 rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
299     cricket::MediaType media_type,
300     const std::string& track_id,
301     MediaStreamTrackInterface::TrackState track_state) {
302   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
303     return FakeAudioTrackForStats::Create(track_id, track_state);
304   } else {
305     RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
306     return FakeVideoTrackForStats::Create(track_id, track_state, nullptr);
307   }
308 }
309 
CreateMockSender(cricket::MediaType media_type,rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc,int attachment_id,std::vector<std::string> local_stream_ids)310 rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
311     cricket::MediaType media_type,
312     rtc::scoped_refptr<MediaStreamTrackInterface> track,
313     uint32_t ssrc,
314     int attachment_id,
315     std::vector<std::string> local_stream_ids) {
316   RTC_DCHECK(!track ||
317              (track->kind() == MediaStreamTrackInterface::kAudioKind &&
318               media_type == cricket::MEDIA_TYPE_AUDIO) ||
319              (track->kind() == MediaStreamTrackInterface::kVideoKind &&
320               media_type == cricket::MEDIA_TYPE_VIDEO));
321   rtc::scoped_refptr<MockRtpSenderInternal> sender(
322       new rtc::RefCountedObject<MockRtpSenderInternal>());
323   EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
324   EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
325   EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type));
326   EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
327     RtpParameters params;
328     params.encodings.push_back(RtpEncodingParameters());
329     params.encodings[0].ssrc = ssrc;
330     return params;
331   }));
332   EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
333   EXPECT_CALL(*sender, stream_ids()).WillRepeatedly(Return(local_stream_ids));
334   return sender;
335 }
336 
CreateMockReceiver(const rtc::scoped_refptr<MediaStreamTrackInterface> & track,uint32_t ssrc,int attachment_id)337 rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
338     const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
339     uint32_t ssrc,
340     int attachment_id) {
341   rtc::scoped_refptr<MockRtpReceiverInternal> receiver(
342       new rtc::RefCountedObject<MockRtpReceiverInternal>());
343   EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
344   EXPECT_CALL(*receiver, streams())
345       .WillRepeatedly(
346           Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>({})));
347 
348   EXPECT_CALL(*receiver, media_type())
349       .WillRepeatedly(
350           Return(track->kind() == MediaStreamTrackInterface::kAudioKind
351                      ? cricket::MEDIA_TYPE_AUDIO
352                      : cricket::MEDIA_TYPE_VIDEO));
353   EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
354     RtpParameters params;
355     params.encodings.push_back(RtpEncodingParameters());
356     params.encodings[0].ssrc = ssrc;
357     return params;
358   }));
359   EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
360   return receiver;
361 }
362 
363 class RTCStatsCollectorWrapper {
364  public:
RTCStatsCollectorWrapper(rtc::scoped_refptr<FakePeerConnectionForStats> pc)365   explicit RTCStatsCollectorWrapper(
366       rtc::scoped_refptr<FakePeerConnectionForStats> pc)
367       : pc_(pc),
368         stats_collector_(
369             RTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec)) {
370   }
371 
stats_collector()372   rtc::scoped_refptr<RTCStatsCollector> stats_collector() {
373     return stats_collector_;
374   }
375 
GetStatsReport()376   rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
377     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
378     stats_collector_->GetStatsReport(callback);
379     return WaitForReport(callback);
380   }
381 
GetStatsReportWithSenderSelector(rtc::scoped_refptr<RtpSenderInternal> selector)382   rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithSenderSelector(
383       rtc::scoped_refptr<RtpSenderInternal> selector) {
384     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
385     stats_collector_->GetStatsReport(selector, callback);
386     return WaitForReport(callback);
387   }
388 
GetStatsReportWithReceiverSelector(rtc::scoped_refptr<RtpReceiverInternal> selector)389   rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithReceiverSelector(
390       rtc::scoped_refptr<RtpReceiverInternal> selector) {
391     rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
392     stats_collector_->GetStatsReport(selector, callback);
393     return WaitForReport(callback);
394   }
395 
GetFreshStatsReport()396   rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
397     stats_collector_->ClearCachedStatsReport();
398     return GetStatsReport();
399   }
400 
SetupLocalTrackAndSender(cricket::MediaType media_type,const std::string & track_id,uint32_t ssrc,bool add_stream,int attachment_id)401   rtc::scoped_refptr<MockRtpSenderInternal> SetupLocalTrackAndSender(
402       cricket::MediaType media_type,
403       const std::string& track_id,
404       uint32_t ssrc,
405       bool add_stream,
406       int attachment_id) {
407     rtc::scoped_refptr<MediaStream> local_stream;
408     if (add_stream) {
409       local_stream = MediaStream::Create("LocalStreamId");
410       pc_->mutable_local_streams()->AddStream(local_stream);
411     }
412 
413     rtc::scoped_refptr<MediaStreamTrackInterface> track;
414     if (media_type == cricket::MEDIA_TYPE_AUDIO) {
415       track = CreateFakeTrack(media_type, track_id,
416                               MediaStreamTrackInterface::kLive);
417       if (add_stream) {
418         local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
419       }
420     } else {
421       track = CreateFakeTrack(media_type, track_id,
422                               MediaStreamTrackInterface::kLive);
423       if (add_stream) {
424         local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
425       }
426     }
427 
428     rtc::scoped_refptr<MockRtpSenderInternal> sender =
429         CreateMockSender(media_type, track, ssrc, attachment_id, {});
430     pc_->AddSender(sender);
431     return sender;
432   }
433 
SetupRemoteTrackAndReceiver(cricket::MediaType media_type,const std::string & track_id,const std::string & stream_id,uint32_t ssrc)434   rtc::scoped_refptr<MockRtpReceiverInternal> SetupRemoteTrackAndReceiver(
435       cricket::MediaType media_type,
436       const std::string& track_id,
437       const std::string& stream_id,
438       uint32_t ssrc) {
439     rtc::scoped_refptr<MediaStream> remote_stream =
440         MediaStream::Create(stream_id);
441     pc_->mutable_remote_streams()->AddStream(remote_stream);
442 
443     rtc::scoped_refptr<MediaStreamTrackInterface> track;
444     if (media_type == cricket::MEDIA_TYPE_AUDIO) {
445       track = CreateFakeTrack(media_type, track_id,
446                               MediaStreamTrackInterface::kLive);
447       remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
448     } else {
449       track = CreateFakeTrack(media_type, track_id,
450                               MediaStreamTrackInterface::kLive);
451       remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
452     }
453 
454     rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
455         CreateMockReceiver(track, ssrc, 62);
456     EXPECT_CALL(*receiver, streams())
457         .WillRepeatedly(
458             Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
459                 {remote_stream})));
460     pc_->AddReceiver(receiver);
461     return receiver;
462   }
463 
464   // Attaches tracks to peer connections by configuring RTP senders and RTP
465   // receivers according to the tracks' pairings with
466   // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
467   // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
468   // be associated with one |[Voice/Video]ReceiverInfo|.
469   // 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)470   void CreateMockRtpSendersReceiversAndChannels(
471       std::initializer_list<
472           std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
473           local_audio_track_info_pairs,
474       std::initializer_list<
475           std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
476           remote_audio_track_info_pairs,
477       std::initializer_list<
478           std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
479           local_video_track_info_pairs,
480       std::initializer_list<
481           std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
482           remote_video_track_info_pairs,
483       std::vector<std::string> local_stream_ids,
484       std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
485     cricket::VoiceMediaInfo voice_media_info;
486     cricket::VideoMediaInfo video_media_info;
487 
488     // Local audio tracks and voice sender infos
489     for (auto& pair : local_audio_track_info_pairs) {
490       MediaStreamTrackInterface* local_audio_track = pair.first;
491       const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
492       RTC_DCHECK_EQ(local_audio_track->kind(),
493                     MediaStreamTrackInterface::kAudioKind);
494 
495       voice_media_info.senders.push_back(voice_sender_info);
496       rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
497           cricket::MEDIA_TYPE_AUDIO,
498           rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
499           voice_sender_info.local_stats[0].ssrc,
500           voice_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
501       pc_->AddSender(rtp_sender);
502     }
503 
504     // Remote audio tracks and voice receiver infos
505     for (auto& pair : remote_audio_track_info_pairs) {
506       MediaStreamTrackInterface* remote_audio_track = pair.first;
507       const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
508       RTC_DCHECK_EQ(remote_audio_track->kind(),
509                     MediaStreamTrackInterface::kAudioKind);
510 
511       voice_media_info.receivers.push_back(voice_receiver_info);
512       rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
513           CreateMockReceiver(
514               rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
515               voice_receiver_info.local_stats[0].ssrc,
516               voice_receiver_info.local_stats[0].ssrc + 10);
517       EXPECT_CALL(*rtp_receiver, streams())
518           .WillRepeatedly(Return(remote_streams));
519       pc_->AddReceiver(rtp_receiver);
520     }
521 
522     // Local video tracks and video sender infos
523     for (auto& pair : local_video_track_info_pairs) {
524       MediaStreamTrackInterface* local_video_track = pair.first;
525       const cricket::VideoSenderInfo& video_sender_info = pair.second;
526       RTC_DCHECK_EQ(local_video_track->kind(),
527                     MediaStreamTrackInterface::kVideoKind);
528 
529       video_media_info.senders.push_back(video_sender_info);
530       video_media_info.aggregated_senders.push_back(video_sender_info);
531       rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
532           cricket::MEDIA_TYPE_VIDEO,
533           rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
534           video_sender_info.local_stats[0].ssrc,
535           video_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
536       pc_->AddSender(rtp_sender);
537     }
538 
539     // Remote video tracks and video receiver infos
540     for (auto& pair : remote_video_track_info_pairs) {
541       MediaStreamTrackInterface* remote_video_track = pair.first;
542       const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
543       RTC_DCHECK_EQ(remote_video_track->kind(),
544                     MediaStreamTrackInterface::kVideoKind);
545 
546       video_media_info.receivers.push_back(video_receiver_info);
547       rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
548           CreateMockReceiver(
549               rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
550               video_receiver_info.local_stats[0].ssrc,
551               video_receiver_info.local_stats[0].ssrc + 10);
552       EXPECT_CALL(*rtp_receiver, streams())
553           .WillRepeatedly(Return(remote_streams));
554       pc_->AddReceiver(rtp_receiver);
555     }
556 
557     auto* voice_media_channel = pc_->AddVoiceChannel("audio", "transport");
558     voice_media_channel->SetStats(voice_media_info);
559 
560     auto* video_media_channel = pc_->AddVideoChannel("video", "transport");
561     video_media_channel->SetStats(video_media_info);
562   }
563 
564  private:
WaitForReport(rtc::scoped_refptr<RTCStatsObtainer> callback)565   rtc::scoped_refptr<const RTCStatsReport> WaitForReport(
566       rtc::scoped_refptr<RTCStatsObtainer> callback) {
567     EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
568     int64_t after = rtc::TimeUTCMicros();
569     for (const RTCStats& stats : *callback->report()) {
570       EXPECT_LE(stats.timestamp_us(), after);
571     }
572     return callback->report();
573   }
574 
575   rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
576   rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
577 };
578 
579 class RTCStatsCollectorTest : public ::testing::Test {
580  public:
RTCStatsCollectorTest()581   RTCStatsCollectorTest()
582       : pc_(new rtc::RefCountedObject<FakePeerConnectionForStats>()),
583         stats_(new RTCStatsCollectorWrapper(pc_)) {}
584 
ExpectReportContainsCertificateInfo(const rtc::scoped_refptr<const RTCStatsReport> & report,const CertificateInfo & certinfo)585   void ExpectReportContainsCertificateInfo(
586       const rtc::scoped_refptr<const RTCStatsReport>& report,
587       const CertificateInfo& certinfo) {
588     for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
589       RTCCertificateStats expected_certificate_stats(
590           "RTCCertificate_" + certinfo.fingerprints[i], report->timestamp_us());
591       expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
592       expected_certificate_stats.fingerprint_algorithm = "sha-1";
593       expected_certificate_stats.base64_certificate = certinfo.pems[i];
594       if (i + 1 < certinfo.fingerprints.size()) {
595         expected_certificate_stats.issuer_certificate_id =
596             "RTCCertificate_" + certinfo.fingerprints[i + 1];
597       }
598       ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
599       EXPECT_EQ(expected_certificate_stats,
600                 report->Get(expected_certificate_stats.id())
601                     ->cast_to<RTCCertificateStats>());
602     }
603   }
604 
605   struct ExampleStatsGraph {
606     rtc::scoped_refptr<RtpSenderInternal> sender;
607     rtc::scoped_refptr<RtpReceiverInternal> receiver;
608 
609     rtc::scoped_refptr<const RTCStatsReport> full_report;
610     std::string send_codec_id;
611     std::string recv_codec_id;
612     std::string outbound_rtp_id;
613     std::string inbound_rtp_id;
614     std::string transport_id;
615     std::string sender_track_id;
616     std::string receiver_track_id;
617     std::string remote_stream_id;
618     std::string peer_connection_id;
619     std::string media_source_id;
620   };
621 
622   // Sets up the example stats graph (see ASCII art below) used for testing the
623   // stats selection algorithm,
624   // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm.
625   // These tests test the integration of the stats traversal algorithm inside of
626   // RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
627   // traversal tests.
SetupExampleStatsGraphForSelectorTests()628   ExampleStatsGraph SetupExampleStatsGraphForSelectorTests() {
629     ExampleStatsGraph graph;
630 
631     // codec (send)
632     graph.send_codec_id = "RTCCodec_VideoMid_Outbound_1";
633     cricket::VideoMediaInfo video_media_info;
634     RtpCodecParameters send_codec;
635     send_codec.payload_type = 1;
636     send_codec.clock_rate = 0;
637     video_media_info.send_codecs.insert(
638         std::make_pair(send_codec.payload_type, send_codec));
639     // codec (recv)
640     graph.recv_codec_id = "RTCCodec_VideoMid_Inbound_2";
641     RtpCodecParameters recv_codec;
642     recv_codec.payload_type = 2;
643     recv_codec.clock_rate = 0;
644     video_media_info.receive_codecs.insert(
645         std::make_pair(recv_codec.payload_type, recv_codec));
646     // outbound-rtp
647     graph.outbound_rtp_id = "RTCOutboundRTPVideoStream_3";
648     video_media_info.senders.push_back(cricket::VideoSenderInfo());
649     video_media_info.senders[0].local_stats.push_back(
650         cricket::SsrcSenderInfo());
651     video_media_info.senders[0].local_stats[0].ssrc = 3;
652     video_media_info.senders[0].codec_payload_type = send_codec.payload_type;
653     video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
654     // inbound-rtp
655     graph.inbound_rtp_id = "RTCInboundRTPVideoStream_4";
656     video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
657     video_media_info.receivers[0].local_stats.push_back(
658         cricket::SsrcReceiverInfo());
659     video_media_info.receivers[0].local_stats[0].ssrc = 4;
660     video_media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
661     // transport
662     graph.transport_id = "RTCTransport_TransportName_1";
663     auto* video_media_channel =
664         pc_->AddVideoChannel("VideoMid", "TransportName");
665     video_media_channel->SetStats(video_media_info);
666     // track (sender)
667     graph.sender = stats_->SetupLocalTrackAndSender(
668         cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false, 50);
669     graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
670                             rtc::ToString(graph.sender->AttachmentId());
671     // track (receiver) and stream (remote stream)
672     graph.receiver = stats_->SetupRemoteTrackAndReceiver(
673         cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
674     graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
675                               rtc::ToString(graph.receiver->AttachmentId());
676     graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
677     // peer-connection
678     graph.peer_connection_id = "RTCPeerConnection";
679     // media-source (kind: video)
680     graph.media_source_id =
681         "RTCVideoSource_" + rtc::ToString(graph.sender->AttachmentId());
682 
683     // Expected stats graph:
684     //
685     //  +--- track (sender)      stream (remote stream) ---> track (receiver)
686     //  |             ^                                        ^
687     //  |             |                                        |
688     //  | +--------- outbound-rtp   inbound-rtp ---------------+
689     //  | |           |        |     |       |
690     //  | |           v        v     v       v
691     //  | |  codec (send)     transport     codec (recv)     peer-connection
692     //  v v
693     //  media-source
694 
695     // Verify the stats graph is set up correctly.
696     graph.full_report = stats_->GetStatsReport();
697     EXPECT_EQ(graph.full_report->size(), 10u);
698     EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
699     EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
700     EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
701     EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
702     EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
703     EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
704     EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
705     EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
706     EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
707     EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
708     const auto& sender_track = graph.full_report->Get(graph.sender_track_id)
709                                    ->cast_to<RTCMediaStreamTrackStats>();
710     EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
711     const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
712                                    ->cast_to<RTCOutboundRTPStreamStats>();
713     EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
714     EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
715     EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
716     EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
717     const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
718                                   ->cast_to<RTCInboundRTPStreamStats>();
719     EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
720     EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
721     EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
722 
723     return graph;
724   }
725 
726  protected:
727   rtc::ScopedFakeClock fake_clock_;
728   rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
729   std::unique_ptr<RTCStatsCollectorWrapper> stats_;
730 };
731 
TEST_F(RTCStatsCollectorTest,SingleCallback)732 TEST_F(RTCStatsCollectorTest, SingleCallback) {
733   rtc::scoped_refptr<const RTCStatsReport> result;
734   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
735   EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
736 }
737 
TEST_F(RTCStatsCollectorTest,MultipleCallbacks)738 TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
739   rtc::scoped_refptr<const RTCStatsReport> a, b, c;
740   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
741   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
742   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
743   EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
744   EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
745   EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
746 
747   EXPECT_EQ(a.get(), b.get());
748   EXPECT_EQ(b.get(), c.get());
749 }
750 
TEST_F(RTCStatsCollectorTest,CachedStatsReports)751 TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
752   // Caching should ensure |a| and |b| are the same report.
753   rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
754   rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
755   EXPECT_EQ(a.get(), b.get());
756   // Invalidate cache by clearing it.
757   stats_->stats_collector()->ClearCachedStatsReport();
758   rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
759   EXPECT_NE(b.get(), c.get());
760   // Invalidate cache by advancing time.
761   fake_clock_.AdvanceTime(TimeDelta::Millis(51));
762   rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
763   EXPECT_TRUE(d);
764   EXPECT_NE(c.get(), d.get());
765 }
766 
TEST_F(RTCStatsCollectorTest,MultipleCallbacksWithInvalidatedCacheInBetween)767 TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
768   rtc::scoped_refptr<const RTCStatsReport> a, b, c;
769   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
770   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
771   // Cache is invalidated after 50 ms.
772   fake_clock_.AdvanceTime(TimeDelta::Millis(51));
773   stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
774   EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
775   EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
776   EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
777   EXPECT_EQ(a.get(), b.get());
778   // The act of doing |AdvanceTime| processes all messages. If this was not the
779   // case we might not require |c| to be fresher than |b|.
780   EXPECT_NE(c.get(), b.get());
781 }
782 
TEST_F(RTCStatsCollectorTest,ToJsonProducesParseableJson)783 TEST_F(RTCStatsCollectorTest, ToJsonProducesParseableJson) {
784   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
785   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
786   std::string json_format = report->ToJson();
787   Json::Reader reader;
788   Json::Value json_value;
789   ASSERT_TRUE(reader.parse(json_format, json_value));
790   // A very brief sanity check on the result.
791   EXPECT_EQ(report->size(), json_value.size());
792 }
793 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsSingle)794 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
795   const char kTransportName[] = "transport";
796 
797   pc_->AddVoiceChannel("audio", kTransportName);
798 
799   std::unique_ptr<CertificateInfo> local_certinfo =
800       CreateFakeCertificateAndInfoFromDers(
801           std::vector<std::string>({"(local) single certificate"}));
802   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
803 
804   std::unique_ptr<CertificateInfo> remote_certinfo =
805       CreateFakeCertificateAndInfoFromDers(
806           std::vector<std::string>({"(remote) single certificate"}));
807   pc_->SetRemoteCertChain(
808       kTransportName,
809       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
810 
811   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
812 
813   ExpectReportContainsCertificateInfo(report, *local_certinfo);
814   ExpectReportContainsCertificateInfo(report, *remote_certinfo);
815 }
816 
TEST_F(RTCStatsCollectorTest,CollectRTCCodecStats)817 TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
818   // Audio
819   cricket::VoiceMediaInfo voice_media_info;
820 
821   RtpCodecParameters inbound_audio_codec;
822   inbound_audio_codec.payload_type = 1;
823   inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
824   inbound_audio_codec.name = "opus";
825   inbound_audio_codec.clock_rate = 1337;
826   inbound_audio_codec.num_channels = 1;
827   inbound_audio_codec.parameters = {{"minptime", "10"}, {"useinbandfec", "1"}};
828   voice_media_info.receive_codecs.insert(
829       std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
830 
831   RtpCodecParameters outbound_audio_codec;
832   outbound_audio_codec.payload_type = 2;
833   outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
834   outbound_audio_codec.name = "isac";
835   outbound_audio_codec.clock_rate = 1338;
836   outbound_audio_codec.num_channels = 2;
837   voice_media_info.send_codecs.insert(
838       std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
839 
840   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
841   voice_media_channel->SetStats(voice_media_info);
842 
843   // Video
844   cricket::VideoMediaInfo video_media_info;
845 
846   RtpCodecParameters inbound_video_codec;
847   inbound_video_codec.payload_type = 3;
848   inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
849   inbound_video_codec.name = "H264";
850   inbound_video_codec.clock_rate = 1339;
851   inbound_video_codec.parameters = {{"level-asymmetry-allowed", "1"},
852                                     {"packetization-mode", "1"},
853                                     {"profile-level-id", "42001f"}};
854   video_media_info.receive_codecs.insert(
855       std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
856 
857   RtpCodecParameters outbound_video_codec;
858   outbound_video_codec.payload_type = 4;
859   outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
860   outbound_video_codec.name = "VP8";
861   outbound_video_codec.clock_rate = 1340;
862   video_media_info.send_codecs.insert(
863       std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
864 
865   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
866   video_media_channel->SetStats(video_media_info);
867 
868   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
869 
870   RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1",
871                                              report->timestamp_us());
872   expected_inbound_audio_codec.payload_type = 1;
873   expected_inbound_audio_codec.mime_type = "audio/opus";
874   expected_inbound_audio_codec.clock_rate = 1337;
875   expected_inbound_audio_codec.channels = 1;
876   expected_inbound_audio_codec.sdp_fmtp_line = "minptime=10;useinbandfec=1";
877 
878   RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
879                                               report->timestamp_us());
880   expected_outbound_audio_codec.payload_type = 2;
881   expected_outbound_audio_codec.mime_type = "audio/isac";
882   expected_outbound_audio_codec.clock_rate = 1338;
883   expected_outbound_audio_codec.channels = 2;
884 
885   RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
886                                              report->timestamp_us());
887   expected_inbound_video_codec.payload_type = 3;
888   expected_inbound_video_codec.mime_type = "video/H264";
889   expected_inbound_video_codec.clock_rate = 1339;
890   expected_inbound_video_codec.sdp_fmtp_line =
891       "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f";
892 
893   RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
894                                               report->timestamp_us());
895   expected_outbound_video_codec.payload_type = 4;
896   expected_outbound_video_codec.mime_type = "video/VP8";
897   expected_outbound_video_codec.clock_rate = 1340;
898 
899   ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
900   EXPECT_EQ(
901       expected_inbound_audio_codec,
902       report->Get(expected_inbound_audio_codec.id())->cast_to<RTCCodecStats>());
903 
904   ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
905   EXPECT_EQ(expected_outbound_audio_codec,
906             report->Get(expected_outbound_audio_codec.id())
907                 ->cast_to<RTCCodecStats>());
908 
909   ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
910   EXPECT_EQ(
911       expected_inbound_video_codec,
912       report->Get(expected_inbound_video_codec.id())->cast_to<RTCCodecStats>());
913 
914   ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
915   EXPECT_EQ(expected_outbound_video_codec,
916             report->Get(expected_outbound_video_codec.id())
917                 ->cast_to<RTCCodecStats>());
918 }
919 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsMultiple)920 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
921   const char kAudioTransport[] = "audio";
922   const char kVideoTransport[] = "video";
923 
924   pc_->AddVoiceChannel("audio", kAudioTransport);
925   std::unique_ptr<CertificateInfo> audio_local_certinfo =
926       CreateFakeCertificateAndInfoFromDers(
927           std::vector<std::string>({"(local) audio"}));
928   pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
929   std::unique_ptr<CertificateInfo> audio_remote_certinfo =
930       CreateFakeCertificateAndInfoFromDers(
931           std::vector<std::string>({"(remote) audio"}));
932   pc_->SetRemoteCertChain(
933       kAudioTransport,
934       audio_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
935 
936   pc_->AddVideoChannel("video", kVideoTransport);
937   std::unique_ptr<CertificateInfo> video_local_certinfo =
938       CreateFakeCertificateAndInfoFromDers(
939           std::vector<std::string>({"(local) video"}));
940   pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
941   std::unique_ptr<CertificateInfo> video_remote_certinfo =
942       CreateFakeCertificateAndInfoFromDers(
943           std::vector<std::string>({"(remote) video"}));
944   pc_->SetRemoteCertChain(
945       kVideoTransport,
946       video_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
947 
948   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
949   ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
950   ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
951   ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
952   ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
953 }
954 
TEST_F(RTCStatsCollectorTest,CollectRTCCertificateStatsChain)955 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
956   const char kTransportName[] = "transport";
957 
958   pc_->AddVoiceChannel("audio", kTransportName);
959 
960   std::unique_ptr<CertificateInfo> local_certinfo =
961       CreateFakeCertificateAndInfoFromDers(
962           {"(local) this", "(local) is", "(local) a", "(local) chain"});
963   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
964 
965   std::unique_ptr<CertificateInfo> remote_certinfo =
966       CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
967                                             "(remote) another",
968                                             "(remote) chain"});
969   pc_->SetRemoteCertChain(
970       kTransportName,
971       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
972 
973   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
974   ExpectReportContainsCertificateInfo(report, *local_certinfo);
975   ExpectReportContainsCertificateInfo(report, *remote_certinfo);
976 }
977 
TEST_F(RTCStatsCollectorTest,CollectTwoRTCDataChannelStatsWithPendingId)978 TEST_F(RTCStatsCollectorTest, CollectTwoRTCDataChannelStatsWithPendingId) {
979   pc_->AddSctpDataChannel(
980       new MockSctpDataChannel(/*id=*/-1, DataChannelInterface::kConnecting));
981   pc_->AddSctpDataChannel(
982       new MockSctpDataChannel(/*id=*/-1, DataChannelInterface::kConnecting));
983 
984   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
985 }
986 
TEST_F(RTCStatsCollectorTest,CollectRTCDataChannelStats)987 TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
988   // Note: The test assumes data channel IDs are predictable.
989   // This is not a safe assumption, but in order to make it work for
990   // the test, we reset the ID allocator at test start.
991   SctpDataChannel::ResetInternalIdAllocatorForTesting(-1);
992   pc_->AddSctpDataChannel(new MockSctpDataChannel(
993       0, "MockSctpDataChannel0", DataChannelInterface::kConnecting, "udp", 1, 2,
994       3, 4));
995   RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0);
996   expected_data_channel0.label = "MockSctpDataChannel0";
997   expected_data_channel0.protocol = "udp";
998   expected_data_channel0.data_channel_identifier = 0;
999   expected_data_channel0.state = "connecting";
1000   expected_data_channel0.messages_sent = 1;
1001   expected_data_channel0.bytes_sent = 2;
1002   expected_data_channel0.messages_received = 3;
1003   expected_data_channel0.bytes_received = 4;
1004 
1005   pc_->AddSctpDataChannel(new MockSctpDataChannel(1, "MockSctpDataChannel1",
1006                                                   DataChannelInterface::kOpen,
1007                                                   "tcp", 5, 6, 7, 8));
1008   RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0);
1009   expected_data_channel1.label = "MockSctpDataChannel1";
1010   expected_data_channel1.protocol = "tcp";
1011   expected_data_channel1.data_channel_identifier = 1;
1012   expected_data_channel1.state = "open";
1013   expected_data_channel1.messages_sent = 5;
1014   expected_data_channel1.bytes_sent = 6;
1015   expected_data_channel1.messages_received = 7;
1016   expected_data_channel1.bytes_received = 8;
1017 
1018   pc_->AddSctpDataChannel(new MockSctpDataChannel(
1019       2, "MockSctpDataChannel2", DataChannelInterface::kClosing, "udp", 9, 10,
1020       11, 12));
1021   RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0);
1022   expected_data_channel2.label = "MockSctpDataChannel2";
1023   expected_data_channel2.protocol = "udp";
1024   expected_data_channel2.data_channel_identifier = 2;
1025   expected_data_channel2.state = "closing";
1026   expected_data_channel2.messages_sent = 9;
1027   expected_data_channel2.bytes_sent = 10;
1028   expected_data_channel2.messages_received = 11;
1029   expected_data_channel2.bytes_received = 12;
1030 
1031   pc_->AddSctpDataChannel(new MockSctpDataChannel(3, "MockSctpDataChannel3",
1032                                                   DataChannelInterface::kClosed,
1033                                                   "tcp", 13, 14, 15, 16));
1034   RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0);
1035   expected_data_channel3.label = "MockSctpDataChannel3";
1036   expected_data_channel3.protocol = "tcp";
1037   expected_data_channel3.data_channel_identifier = 3;
1038   expected_data_channel3.state = "closed";
1039   expected_data_channel3.messages_sent = 13;
1040   expected_data_channel3.bytes_sent = 14;
1041   expected_data_channel3.messages_received = 15;
1042   expected_data_channel3.bytes_received = 16;
1043 
1044   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1045 
1046   ASSERT_TRUE(report->Get(expected_data_channel0.id()));
1047   EXPECT_EQ(
1048       expected_data_channel0,
1049       report->Get(expected_data_channel0.id())->cast_to<RTCDataChannelStats>());
1050   ASSERT_TRUE(report->Get(expected_data_channel1.id()));
1051   EXPECT_EQ(
1052       expected_data_channel1,
1053       report->Get(expected_data_channel1.id())->cast_to<RTCDataChannelStats>());
1054   ASSERT_TRUE(report->Get(expected_data_channel2.id()));
1055   EXPECT_EQ(
1056       expected_data_channel2,
1057       report->Get(expected_data_channel2.id())->cast_to<RTCDataChannelStats>());
1058   ASSERT_TRUE(report->Get(expected_data_channel3.id()));
1059   EXPECT_EQ(
1060       expected_data_channel3,
1061       report->Get(expected_data_channel3.id())->cast_to<RTCDataChannelStats>());
1062 }
1063 
TEST_F(RTCStatsCollectorTest,CollectRTCIceCandidateStats)1064 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
1065   // Candidates in the first transport stats.
1066   std::unique_ptr<cricket::Candidate> a_local_host =
1067       CreateFakeCandidate("1.2.3.4", 5, "a_local_host's protocol",
1068                           rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0);
1069   RTCLocalIceCandidateStats expected_a_local_host(
1070       "RTCIceCandidate_" + a_local_host->id(), 0);
1071   expected_a_local_host.transport_id = "RTCTransport_a_0";
1072   expected_a_local_host.network_type = "vpn";
1073   expected_a_local_host.ip = "1.2.3.4";
1074   expected_a_local_host.port = 5;
1075   expected_a_local_host.protocol = "a_local_host's protocol";
1076   expected_a_local_host.candidate_type = "host";
1077   expected_a_local_host.priority = 0;
1078   EXPECT_FALSE(*expected_a_local_host.is_remote);
1079 
1080   std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
1081       "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1082       cricket::STUN_PORT_TYPE, 1);
1083   RTCRemoteIceCandidateStats expected_a_remote_srflx(
1084       "RTCIceCandidate_" + a_remote_srflx->id(), 0);
1085   expected_a_remote_srflx.transport_id = "RTCTransport_a_0";
1086   expected_a_remote_srflx.ip = "6.7.8.9";
1087   expected_a_remote_srflx.port = 10;
1088   expected_a_remote_srflx.protocol = "remote_srflx's protocol";
1089   expected_a_remote_srflx.candidate_type = "srflx";
1090   expected_a_remote_srflx.priority = 1;
1091   expected_a_remote_srflx.deleted = false;
1092   EXPECT_TRUE(*expected_a_remote_srflx.is_remote);
1093 
1094   std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
1095       "11.12.13.14", 15, "a_local_prflx's protocol", rtc::ADAPTER_TYPE_CELLULAR,
1096       cricket::PRFLX_PORT_TYPE, 2);
1097   RTCLocalIceCandidateStats expected_a_local_prflx(
1098       "RTCIceCandidate_" + a_local_prflx->id(), 0);
1099   expected_a_local_prflx.transport_id = "RTCTransport_a_0";
1100   expected_a_local_prflx.network_type = "cellular";
1101   expected_a_local_prflx.ip = "11.12.13.14";
1102   expected_a_local_prflx.port = 15;
1103   expected_a_local_prflx.protocol = "a_local_prflx's protocol";
1104   expected_a_local_prflx.candidate_type = "prflx";
1105   expected_a_local_prflx.priority = 2;
1106   expected_a_local_prflx.deleted = false;
1107   EXPECT_FALSE(*expected_a_local_prflx.is_remote);
1108 
1109   std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
1110       "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1111       cricket::RELAY_PORT_TYPE, 3);
1112   RTCRemoteIceCandidateStats expected_a_remote_relay(
1113       "RTCIceCandidate_" + a_remote_relay->id(), 0);
1114   expected_a_remote_relay.transport_id = "RTCTransport_a_0";
1115   expected_a_remote_relay.ip = "16.17.18.19";
1116   expected_a_remote_relay.port = 20;
1117   expected_a_remote_relay.protocol = "a_remote_relay's protocol";
1118   expected_a_remote_relay.candidate_type = "relay";
1119   expected_a_remote_relay.priority = 3;
1120   expected_a_remote_relay.deleted = false;
1121   EXPECT_TRUE(*expected_a_remote_relay.is_remote);
1122 
1123   std::unique_ptr<cricket::Candidate> a_local_relay = CreateFakeCandidate(
1124       "16.17.18.19", 21, "a_local_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1125       cricket::RELAY_PORT_TYPE, 1);
1126   a_local_relay->set_relay_protocol("tcp");
1127 
1128   RTCRemoteIceCandidateStats expected_a_local_relay(
1129       "RTCIceCandidate_" + a_local_relay->id(), 0);
1130   expected_a_local_relay.transport_id = "RTCTransport_a_0";
1131   expected_a_local_relay.ip = "16.17.18.19";
1132   expected_a_local_relay.port = 21;
1133   expected_a_local_relay.protocol = "a_local_relay's protocol";
1134   expected_a_local_relay.relay_protocol = "tcp";
1135   expected_a_local_relay.candidate_type = "relay";
1136   expected_a_local_relay.priority = 1;
1137   expected_a_local_relay.deleted = false;
1138   EXPECT_TRUE(*expected_a_local_relay.is_remote);
1139 
1140   // Candidates in the second transport stats.
1141   std::unique_ptr<cricket::Candidate> b_local =
1142       CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
1143                           rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
1144   RTCLocalIceCandidateStats expected_b_local("RTCIceCandidate_" + b_local->id(),
1145                                              0);
1146   expected_b_local.transport_id = "RTCTransport_b_0";
1147   expected_b_local.network_type = "wifi";
1148   expected_b_local.ip = "42.42.42.42";
1149   expected_b_local.port = 42;
1150   expected_b_local.protocol = "b_local's protocol";
1151   expected_b_local.candidate_type = "host";
1152   expected_b_local.priority = 42;
1153   expected_b_local.deleted = false;
1154   EXPECT_FALSE(*expected_b_local.is_remote);
1155 
1156   std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
1157       "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1158       cricket::LOCAL_PORT_TYPE, 42);
1159   RTCRemoteIceCandidateStats expected_b_remote(
1160       "RTCIceCandidate_" + b_remote->id(), 0);
1161   expected_b_remote.transport_id = "RTCTransport_b_0";
1162   expected_b_remote.ip = "42.42.42.42";
1163   expected_b_remote.port = 42;
1164   expected_b_remote.protocol = "b_remote's protocol";
1165   expected_b_remote.candidate_type = "host";
1166   expected_b_remote.priority = 42;
1167   expected_b_remote.deleted = false;
1168   EXPECT_TRUE(*expected_b_remote.is_remote);
1169 
1170   // Add candidate pairs to connection.
1171   cricket::TransportChannelStats a_transport_channel_stats;
1172   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1173       cricket::ConnectionInfo());
1174   a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1175       .local_candidate = *a_local_host.get();
1176   a_transport_channel_stats.ice_transport_stats.connection_infos[0]
1177       .remote_candidate = *a_remote_srflx.get();
1178   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1179       cricket::ConnectionInfo());
1180   a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1181       .local_candidate = *a_local_prflx.get();
1182   a_transport_channel_stats.ice_transport_stats.connection_infos[1]
1183       .remote_candidate = *a_remote_relay.get();
1184   a_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1185       cricket::ConnectionInfo());
1186   a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1187       .local_candidate = *a_local_relay.get();
1188   a_transport_channel_stats.ice_transport_stats.connection_infos[2]
1189       .remote_candidate = *a_remote_relay.get();
1190 
1191   pc_->AddVoiceChannel("audio", "a");
1192   pc_->SetTransportStats("a", a_transport_channel_stats);
1193 
1194   cricket::TransportChannelStats b_transport_channel_stats;
1195   b_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1196       cricket::ConnectionInfo());
1197   b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1198       .local_candidate = *b_local.get();
1199   b_transport_channel_stats.ice_transport_stats.connection_infos[0]
1200       .remote_candidate = *b_remote.get();
1201 
1202   pc_->AddVideoChannel("video", "b");
1203   pc_->SetTransportStats("b", b_transport_channel_stats);
1204 
1205   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1206 
1207   ASSERT_TRUE(report->Get(expected_a_local_host.id()));
1208   EXPECT_EQ(expected_a_local_host, report->Get(expected_a_local_host.id())
1209                                        ->cast_to<RTCLocalIceCandidateStats>());
1210   ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
1211   EXPECT_EQ(expected_a_remote_srflx,
1212             report->Get(expected_a_remote_srflx.id())
1213                 ->cast_to<RTCRemoteIceCandidateStats>());
1214   ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
1215   EXPECT_EQ(expected_a_local_prflx, report->Get(expected_a_local_prflx.id())
1216                                         ->cast_to<RTCLocalIceCandidateStats>());
1217   ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
1218   EXPECT_EQ(expected_a_remote_relay,
1219             report->Get(expected_a_remote_relay.id())
1220                 ->cast_to<RTCRemoteIceCandidateStats>());
1221   ASSERT_TRUE(report->Get(expected_b_local.id()));
1222   EXPECT_EQ(
1223       expected_b_local,
1224       report->Get(expected_b_local.id())->cast_to<RTCLocalIceCandidateStats>());
1225   ASSERT_TRUE(report->Get(expected_b_remote.id()));
1226   EXPECT_EQ(expected_b_remote, report->Get(expected_b_remote.id())
1227                                    ->cast_to<RTCRemoteIceCandidateStats>());
1228   EXPECT_TRUE(report->Get("RTCTransport_a_0"));
1229   EXPECT_TRUE(report->Get("RTCTransport_b_0"));
1230 }
1231 
TEST_F(RTCStatsCollectorTest,CollectRTCIceCandidatePairStats)1232 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
1233   const char kTransportName[] = "transport";
1234 
1235   std::unique_ptr<cricket::Candidate> local_candidate =
1236       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1237                           cricket::LOCAL_PORT_TYPE, 42);
1238   std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
1239       "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1240       cricket::LOCAL_PORT_TYPE, 42);
1241 
1242   cricket::ConnectionInfo connection_info;
1243   connection_info.best_connection = false;
1244   connection_info.local_candidate = *local_candidate.get();
1245   connection_info.remote_candidate = *remote_candidate.get();
1246   connection_info.writable = true;
1247   connection_info.sent_total_bytes = 42;
1248   connection_info.recv_total_bytes = 1234;
1249   connection_info.total_round_trip_time_ms = 0;
1250   connection_info.current_round_trip_time_ms = absl::nullopt;
1251   connection_info.recv_ping_requests = 2020;
1252   connection_info.sent_ping_requests_total = 2020;
1253   connection_info.sent_ping_requests_before_first_response = 2000;
1254   connection_info.recv_ping_responses = 4321;
1255   connection_info.sent_ping_responses = 1000;
1256   connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
1257   connection_info.priority = 5555;
1258   connection_info.nominated = false;
1259 
1260   cricket::TransportChannelStats transport_channel_stats;
1261   transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1262   transport_channel_stats.ice_transport_stats.connection_infos.push_back(
1263       connection_info);
1264 
1265   pc_->AddVideoChannel("video", kTransportName);
1266   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1267 
1268   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1269 
1270   RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" +
1271                                              local_candidate->id() + "_" +
1272                                              remote_candidate->id(),
1273                                          report->timestamp_us());
1274   expected_pair.transport_id =
1275       "RTCTransport_transport_" +
1276       rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1277   expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
1278   expected_pair.remote_candidate_id =
1279       "RTCIceCandidate_" + remote_candidate->id();
1280   expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1281   expected_pair.priority = 5555;
1282   expected_pair.nominated = false;
1283   expected_pair.writable = true;
1284   expected_pair.bytes_sent = 42;
1285   expected_pair.bytes_received = 1234;
1286   expected_pair.total_round_trip_time = 0.0;
1287   expected_pair.requests_received = 2020;
1288   expected_pair.requests_sent = 2000;
1289   expected_pair.responses_received = 4321;
1290   expected_pair.responses_sent = 1000;
1291   expected_pair.consent_requests_sent = (2020 - 2000);
1292   // |expected_pair.current_round_trip_time| should be undefined because the
1293   // current RTT is not set.
1294   // |expected_pair.available_[outgoing/incoming]_bitrate| should be undefined
1295   // because is is not the current pair.
1296 
1297   ASSERT_TRUE(report->Get(expected_pair.id()));
1298   EXPECT_EQ(
1299       expected_pair,
1300       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1301   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1302 
1303   // Set nominated and "GetStats" again.
1304   transport_channel_stats.ice_transport_stats.connection_infos[0].nominated =
1305       true;
1306   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1307   report = stats_->GetFreshStatsReport();
1308   expected_pair.nominated = true;
1309   ASSERT_TRUE(report->Get(expected_pair.id()));
1310   EXPECT_EQ(
1311       expected_pair,
1312       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1313   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1314 
1315   // Set round trip times and "GetStats" again.
1316   transport_channel_stats.ice_transport_stats.connection_infos[0]
1317       .total_round_trip_time_ms = 7331;
1318   transport_channel_stats.ice_transport_stats.connection_infos[0]
1319       .current_round_trip_time_ms = 1337;
1320   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1321   report = stats_->GetFreshStatsReport();
1322   expected_pair.total_round_trip_time = 7.331;
1323   expected_pair.current_round_trip_time = 1.337;
1324   ASSERT_TRUE(report->Get(expected_pair.id()));
1325   EXPECT_EQ(
1326       expected_pair,
1327       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1328   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1329 
1330   // Make pair the current pair, clear bandwidth and "GetStats" again.
1331   transport_channel_stats.ice_transport_stats.connection_infos[0]
1332       .best_connection = true;
1333   pc_->SetTransportStats(kTransportName, transport_channel_stats);
1334   report = stats_->GetFreshStatsReport();
1335   // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
1336   // undefined because bandwidth is not set.
1337   ASSERT_TRUE(report->Get(expected_pair.id()));
1338   EXPECT_EQ(
1339       expected_pair,
1340       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1341   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1342 
1343   // Set bandwidth and "GetStats" again.
1344   webrtc::Call::Stats call_stats;
1345   const int kSendBandwidth = 888;
1346   call_stats.send_bandwidth_bps = kSendBandwidth;
1347   const int kRecvBandwidth = 999;
1348   call_stats.recv_bandwidth_bps = kRecvBandwidth;
1349   pc_->SetCallStats(call_stats);
1350   report = stats_->GetFreshStatsReport();
1351   expected_pair.available_outgoing_bitrate = kSendBandwidth;
1352   expected_pair.available_incoming_bitrate = kRecvBandwidth;
1353   ASSERT_TRUE(report->Get(expected_pair.id()));
1354   EXPECT_EQ(
1355       expected_pair,
1356       report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1357   EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1358 
1359   RTCLocalIceCandidateStats expected_local_candidate(
1360       *expected_pair.local_candidate_id, report->timestamp_us());
1361   expected_local_candidate.transport_id = *expected_pair.transport_id;
1362   expected_local_candidate.network_type = "wifi";
1363   expected_local_candidate.ip = "42.42.42.42";
1364   expected_local_candidate.port = 42;
1365   expected_local_candidate.protocol = "protocol";
1366   expected_local_candidate.candidate_type = "host";
1367   expected_local_candidate.priority = 42;
1368   expected_local_candidate.deleted = false;
1369   EXPECT_FALSE(*expected_local_candidate.is_remote);
1370   ASSERT_TRUE(report->Get(expected_local_candidate.id()));
1371   EXPECT_EQ(expected_local_candidate,
1372             report->Get(expected_local_candidate.id())
1373                 ->cast_to<RTCLocalIceCandidateStats>());
1374 
1375   RTCRemoteIceCandidateStats expected_remote_candidate(
1376       *expected_pair.remote_candidate_id, report->timestamp_us());
1377   expected_remote_candidate.transport_id = *expected_pair.transport_id;
1378   expected_remote_candidate.ip = "42.42.42.42";
1379   expected_remote_candidate.port = 42;
1380   expected_remote_candidate.protocol = "protocol";
1381   expected_remote_candidate.candidate_type = "host";
1382   expected_remote_candidate.priority = 42;
1383   expected_remote_candidate.deleted = false;
1384   EXPECT_TRUE(*expected_remote_candidate.is_remote);
1385   ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
1386   EXPECT_EQ(expected_remote_candidate,
1387             report->Get(expected_remote_candidate.id())
1388                 ->cast_to<RTCRemoteIceCandidateStats>());
1389 }
1390 
TEST_F(RTCStatsCollectorTest,CollectRTCPeerConnectionStats)1391 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
1392   {
1393     rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1394     RTCPeerConnectionStats expected("RTCPeerConnection",
1395                                     report->timestamp_us());
1396     expected.data_channels_opened = 0;
1397     expected.data_channels_closed = 0;
1398     ASSERT_TRUE(report->Get("RTCPeerConnection"));
1399     EXPECT_EQ(
1400         expected,
1401         report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
1402   }
1403 
1404   // TODO(bugs.webrtc.org/11547): Supply a separate network thread.
1405   FakeDataChannelProvider provider;
1406   rtc::scoped_refptr<SctpDataChannel> dummy_channel_a = SctpDataChannel::Create(
1407       &provider, "DummyChannelA", InternalDataChannelInit(),
1408       rtc::Thread::Current(), rtc::Thread::Current());
1409   pc_->SignalSctpDataChannelCreated()(dummy_channel_a.get());
1410   rtc::scoped_refptr<SctpDataChannel> dummy_channel_b = SctpDataChannel::Create(
1411       &provider, "DummyChannelB", InternalDataChannelInit(),
1412       rtc::Thread::Current(), rtc::Thread::Current());
1413   pc_->SignalSctpDataChannelCreated()(dummy_channel_b.get());
1414 
1415   dummy_channel_a->SignalOpened(dummy_channel_a.get());
1416   // Closing a channel that is not opened should not affect the counts.
1417   dummy_channel_b->SignalClosed(dummy_channel_b.get());
1418 
1419   {
1420     rtc::scoped_refptr<const RTCStatsReport> report =
1421         stats_->GetFreshStatsReport();
1422     RTCPeerConnectionStats expected("RTCPeerConnection",
1423                                     report->timestamp_us());
1424     expected.data_channels_opened = 1;
1425     expected.data_channels_closed = 0;
1426     ASSERT_TRUE(report->Get("RTCPeerConnection"));
1427     EXPECT_EQ(
1428         expected,
1429         report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
1430   }
1431 
1432   dummy_channel_b->SignalOpened(dummy_channel_b.get());
1433   dummy_channel_b->SignalClosed(dummy_channel_b.get());
1434 
1435   {
1436     rtc::scoped_refptr<const RTCStatsReport> report =
1437         stats_->GetFreshStatsReport();
1438     RTCPeerConnectionStats expected("RTCPeerConnection",
1439                                     report->timestamp_us());
1440     expected.data_channels_opened = 2;
1441     expected.data_channels_closed = 1;
1442     ASSERT_TRUE(report->Get("RTCPeerConnection"));
1443     EXPECT_EQ(
1444         expected,
1445         report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
1446   }
1447 
1448   // Re-opening a data channel (or opening a new data channel that is re-using
1449   // the same address in memory) should increase the opened count.
1450   dummy_channel_b->SignalOpened(dummy_channel_b.get());
1451 
1452   {
1453     rtc::scoped_refptr<const RTCStatsReport> report =
1454         stats_->GetFreshStatsReport();
1455     RTCPeerConnectionStats expected("RTCPeerConnection",
1456                                     report->timestamp_us());
1457     expected.data_channels_opened = 3;
1458     expected.data_channels_closed = 1;
1459     ASSERT_TRUE(report->Get("RTCPeerConnection"));
1460     EXPECT_EQ(
1461         expected,
1462         report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
1463   }
1464 
1465   dummy_channel_a->SignalClosed(dummy_channel_a.get());
1466   dummy_channel_b->SignalClosed(dummy_channel_b.get());
1467 
1468   {
1469     rtc::scoped_refptr<const RTCStatsReport> report =
1470         stats_->GetFreshStatsReport();
1471     RTCPeerConnectionStats expected("RTCPeerConnection",
1472                                     report->timestamp_us());
1473     expected.data_channels_opened = 3;
1474     expected.data_channels_closed = 3;
1475     ASSERT_TRUE(report->Get("RTCPeerConnection"));
1476     EXPECT_EQ(
1477         expected,
1478         report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
1479   }
1480 }
1481 
TEST_F(RTCStatsCollectorTest,CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio)1482 TEST_F(RTCStatsCollectorTest,
1483        CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
1484   rtc::scoped_refptr<MediaStream> local_stream =
1485       MediaStream::Create("LocalStreamId");
1486   pc_->mutable_local_streams()->AddStream(local_stream);
1487 
1488   // Local audio track
1489   rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
1490       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
1491                       MediaStreamTrackInterface::kEnded);
1492   local_stream->AddTrack(
1493       static_cast<AudioTrackInterface*>(local_audio_track.get()));
1494 
1495   cricket::VoiceSenderInfo voice_sender_info_ssrc1;
1496   voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1497   voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
1498   voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
1499   voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
1500 
1501   stats_->CreateMockRtpSendersReceiversAndChannels(
1502       {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
1503       {}, {}, {local_stream->id()}, {});
1504 
1505   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1506 
1507   RTCMediaStreamStats expected_local_stream(
1508       IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
1509   expected_local_stream.stream_identifier = local_stream->id();
1510   expected_local_stream.track_ids = {
1511       IdForType<RTCMediaStreamTrackStats>(report)};
1512   ASSERT_TRUE(report->Get(expected_local_stream.id()))
1513       << "Did not find " << expected_local_stream.id() << " in "
1514       << report->ToJson();
1515   EXPECT_EQ(
1516       expected_local_stream,
1517       report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1518 
1519   RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
1520       IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1521       RTCMediaStreamTrackKind::kAudio);
1522   expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
1523   expected_local_audio_track_ssrc1.media_source_id =
1524       "RTCAudioSource_11";  // Attachment ID = SSRC + 10
1525   expected_local_audio_track_ssrc1.remote_source = false;
1526   expected_local_audio_track_ssrc1.ended = true;
1527   expected_local_audio_track_ssrc1.detached = false;
1528   expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
1529   expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
1530   ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
1531       << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
1532       << report->ToJson();
1533   EXPECT_EQ(expected_local_audio_track_ssrc1,
1534             report->Get(expected_local_audio_track_ssrc1.id())
1535                 ->cast_to<RTCMediaStreamTrackStats>());
1536 }
1537 
TEST_F(RTCStatsCollectorTest,CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio)1538 TEST_F(RTCStatsCollectorTest,
1539        CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
1540   rtc::scoped_refptr<MediaStream> remote_stream =
1541       MediaStream::Create("RemoteStreamId");
1542   pc_->mutable_remote_streams()->AddStream(remote_stream);
1543 
1544   // Remote audio track
1545   rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
1546       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
1547                       MediaStreamTrackInterface::kLive);
1548   remote_stream->AddTrack(
1549       static_cast<AudioTrackInterface*>(remote_audio_track.get()));
1550 
1551   cricket::VoiceReceiverInfo voice_receiver_info;
1552   voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
1553   voice_receiver_info.local_stats[0].ssrc = 3;
1554   voice_receiver_info.audio_level = 16383;  // [0,32767]
1555   voice_receiver_info.total_output_energy = 0.125;
1556   voice_receiver_info.total_samples_received = 4567;
1557   voice_receiver_info.total_output_duration = 0.25;
1558   voice_receiver_info.concealed_samples = 123;
1559   voice_receiver_info.concealment_events = 12;
1560   voice_receiver_info.inserted_samples_for_deceleration = 987;
1561   voice_receiver_info.removed_samples_for_acceleration = 876;
1562   voice_receiver_info.silent_concealed_samples = 765;
1563   voice_receiver_info.jitter_buffer_delay_seconds = 3456;
1564   voice_receiver_info.jitter_buffer_emitted_count = 13;
1565   voice_receiver_info.jitter_buffer_target_delay_seconds = 7.894;
1566   voice_receiver_info.jitter_buffer_flushes = 7;
1567   voice_receiver_info.delayed_packet_outage_samples = 15;
1568   voice_receiver_info.relative_packet_arrival_delay_seconds = 16;
1569   voice_receiver_info.interruption_count = 7788;
1570   voice_receiver_info.total_interruption_duration_ms = 778899;
1571 
1572   stats_->CreateMockRtpSendersReceiversAndChannels(
1573       {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
1574       {}, {}, {remote_stream});
1575 
1576   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1577 
1578   RTCMediaStreamStats expected_remote_stream(
1579       IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
1580   expected_remote_stream.stream_identifier = remote_stream->id();
1581   expected_remote_stream.track_ids =
1582       std::vector<std::string>({IdForType<RTCMediaStreamTrackStats>(report)});
1583   ASSERT_TRUE(report->Get(expected_remote_stream.id()))
1584       << "Did not find " << expected_remote_stream.id() << " in "
1585       << report->ToJson();
1586   EXPECT_EQ(
1587       expected_remote_stream,
1588       report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
1589 
1590   RTCMediaStreamTrackStats expected_remote_audio_track(
1591       IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1592       RTCMediaStreamTrackKind::kAudio);
1593   expected_remote_audio_track.track_identifier = remote_audio_track->id();
1594   // |expected_remote_audio_track.media_source_id| should be undefined
1595   // because the track is remote.
1596   expected_remote_audio_track.remote_source = true;
1597   expected_remote_audio_track.ended = false;
1598   expected_remote_audio_track.detached = false;
1599   expected_remote_audio_track.audio_level = 16383.0 / 32767.0;  // [0,1]
1600   expected_remote_audio_track.total_audio_energy = 0.125;
1601   expected_remote_audio_track.total_samples_received = 4567;
1602   expected_remote_audio_track.total_samples_duration = 0.25;
1603   expected_remote_audio_track.concealed_samples = 123;
1604   expected_remote_audio_track.concealment_events = 12;
1605   expected_remote_audio_track.inserted_samples_for_deceleration = 987;
1606   expected_remote_audio_track.removed_samples_for_acceleration = 876;
1607   expected_remote_audio_track.silent_concealed_samples = 765;
1608   expected_remote_audio_track.jitter_buffer_delay = 3456;
1609   expected_remote_audio_track.jitter_buffer_emitted_count = 13;
1610   expected_remote_audio_track.jitter_buffer_target_delay = 7.894;
1611   expected_remote_audio_track.jitter_buffer_flushes = 7;
1612   expected_remote_audio_track.delayed_packet_outage_samples = 15;
1613   expected_remote_audio_track.relative_packet_arrival_delay = 16;
1614   expected_remote_audio_track.interruption_count = 7788;
1615   expected_remote_audio_track.total_interruption_duration = 778.899;
1616   ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
1617   EXPECT_EQ(expected_remote_audio_track,
1618             report->Get(expected_remote_audio_track.id())
1619                 ->cast_to<RTCMediaStreamTrackStats>());
1620 }
1621 
TEST_F(RTCStatsCollectorTest,CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video)1622 TEST_F(RTCStatsCollectorTest,
1623        CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
1624   rtc::scoped_refptr<MediaStream> local_stream =
1625       MediaStream::Create("LocalStreamId");
1626   pc_->mutable_local_streams()->AddStream(local_stream);
1627 
1628   // Local video track
1629   rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
1630       CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
1631                       MediaStreamTrackInterface::kLive);
1632   local_stream->AddTrack(
1633       static_cast<VideoTrackInterface*>(local_video_track.get()));
1634 
1635   cricket::VideoSenderInfo video_sender_info_ssrc1;
1636   video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1637   video_sender_info_ssrc1.local_stats[0].ssrc = 1;
1638   video_sender_info_ssrc1.send_frame_width = 1234;
1639   video_sender_info_ssrc1.send_frame_height = 4321;
1640   video_sender_info_ssrc1.frames_encoded = 11;
1641   video_sender_info_ssrc1.huge_frames_sent = 1;
1642 
1643   stats_->CreateMockRtpSendersReceiversAndChannels(
1644       {}, {},
1645       {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
1646       {local_stream->id()}, {});
1647 
1648   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1649 
1650   auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1651   ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1652   auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1653   ASSERT_EQ(1U, stats_of_track_type.size())
1654       << "Wrong number of tracks in " << report->ToJson();
1655 
1656   RTCMediaStreamStats expected_local_stream(stats_of_my_type[0]->id(),
1657                                             report->timestamp_us());
1658   expected_local_stream.stream_identifier = local_stream->id();
1659   expected_local_stream.track_ids =
1660       std::vector<std::string>({stats_of_track_type[0]->id()});
1661   ASSERT_TRUE(report->Get(expected_local_stream.id()));
1662   EXPECT_EQ(
1663       expected_local_stream,
1664       report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1665 
1666   RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
1667       stats_of_track_type[0]->id(), report->timestamp_us(),
1668       RTCMediaStreamTrackKind::kVideo);
1669   expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
1670   expected_local_video_track_ssrc1.media_source_id =
1671       "RTCVideoSource_11";  // Attachment ID = SSRC + 10
1672   expected_local_video_track_ssrc1.remote_source = false;
1673   expected_local_video_track_ssrc1.ended = false;
1674   expected_local_video_track_ssrc1.detached = false;
1675   expected_local_video_track_ssrc1.frame_width = 1234;
1676   expected_local_video_track_ssrc1.frame_height = 4321;
1677   expected_local_video_track_ssrc1.frames_sent = 11;
1678   expected_local_video_track_ssrc1.huge_frames_sent = 1;
1679   ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
1680   EXPECT_EQ(expected_local_video_track_ssrc1,
1681             report->Get(expected_local_video_track_ssrc1.id())
1682                 ->cast_to<RTCMediaStreamTrackStats>());
1683 }
1684 
TEST_F(RTCStatsCollectorTest,CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video)1685 TEST_F(RTCStatsCollectorTest,
1686        CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
1687   rtc::scoped_refptr<MediaStream> remote_stream =
1688       MediaStream::Create("RemoteStreamId");
1689   pc_->mutable_remote_streams()->AddStream(remote_stream);
1690 
1691   // Remote video track with values
1692   rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
1693       CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
1694                       MediaStreamTrackInterface::kEnded);
1695   remote_stream->AddTrack(
1696       static_cast<VideoTrackInterface*>(remote_video_track_ssrc3.get()));
1697 
1698   cricket::VideoReceiverInfo video_receiver_info_ssrc3;
1699   video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
1700   video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
1701   video_receiver_info_ssrc3.frame_width = 6789;
1702   video_receiver_info_ssrc3.frame_height = 9876;
1703   video_receiver_info_ssrc3.jitter_buffer_delay_seconds = 2.5;
1704   video_receiver_info_ssrc3.jitter_buffer_emitted_count = 25;
1705   video_receiver_info_ssrc3.frames_received = 1000;
1706   video_receiver_info_ssrc3.frames_decoded = 995;
1707   video_receiver_info_ssrc3.frames_dropped = 10;
1708   video_receiver_info_ssrc3.frames_rendered = 990;
1709   video_receiver_info_ssrc3.freeze_count = 3;
1710   video_receiver_info_ssrc3.pause_count = 2;
1711   video_receiver_info_ssrc3.total_freezes_duration_ms = 1000;
1712   video_receiver_info_ssrc3.total_pauses_duration_ms = 10000;
1713   video_receiver_info_ssrc3.total_frames_duration_ms = 15000;
1714   video_receiver_info_ssrc3.sum_squared_frame_durations = 1.5;
1715 
1716   stats_->CreateMockRtpSendersReceiversAndChannels(
1717       {}, {}, {},
1718       {std::make_pair(remote_video_track_ssrc3.get(),
1719                       video_receiver_info_ssrc3)},
1720       {}, {remote_stream});
1721 
1722   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1723 
1724   auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1725   ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1726   auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1727   ASSERT_EQ(1U, stats_of_track_type.size())
1728       << "Wrong number of tracks in " << report->ToJson();
1729   ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
1730 
1731   RTCMediaStreamStats expected_remote_stream(stats_of_my_type[0]->id(),
1732                                              report->timestamp_us());
1733   expected_remote_stream.stream_identifier = remote_stream->id();
1734   expected_remote_stream.track_ids =
1735       std::vector<std::string>({stats_of_track_type[0]->id()});
1736   ASSERT_TRUE(report->Get(expected_remote_stream.id()));
1737   EXPECT_EQ(
1738       expected_remote_stream,
1739       report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
1740 
1741   RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
1742       stats_of_track_type[0]->id(), report->timestamp_us(),
1743       RTCMediaStreamTrackKind::kVideo);
1744   expected_remote_video_track_ssrc3.track_identifier =
1745       remote_video_track_ssrc3->id();
1746   // |expected_remote_video_track_ssrc3.media_source_id| should be undefined
1747   // because the track is remote.
1748   expected_remote_video_track_ssrc3.remote_source = true;
1749   expected_remote_video_track_ssrc3.ended = true;
1750   expected_remote_video_track_ssrc3.detached = false;
1751   expected_remote_video_track_ssrc3.frame_width = 6789;
1752   expected_remote_video_track_ssrc3.frame_height = 9876;
1753   expected_remote_video_track_ssrc3.jitter_buffer_delay = 2.5;
1754   expected_remote_video_track_ssrc3.jitter_buffer_emitted_count = 25;
1755   expected_remote_video_track_ssrc3.frames_received = 1000;
1756   expected_remote_video_track_ssrc3.frames_decoded = 995;
1757   expected_remote_video_track_ssrc3.frames_dropped = 10;
1758   expected_remote_video_track_ssrc3.freeze_count = 3;
1759   expected_remote_video_track_ssrc3.pause_count = 2;
1760   expected_remote_video_track_ssrc3.total_freezes_duration = 1;
1761   expected_remote_video_track_ssrc3.total_pauses_duration = 10;
1762   expected_remote_video_track_ssrc3.total_frames_duration = 15;
1763   expected_remote_video_track_ssrc3.sum_squared_frame_durations = 1.5;
1764 
1765   ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
1766   EXPECT_EQ(expected_remote_video_track_ssrc3,
1767             report->Get(expected_remote_video_track_ssrc3.id())
1768                 ->cast_to<RTCMediaStreamTrackStats>());
1769 }
1770 
TEST_F(RTCStatsCollectorTest,CollectRTCInboundRTPStreamStats_Audio)1771 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
1772   cricket::VoiceMediaInfo voice_media_info;
1773 
1774   voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1775   voice_media_info.receivers[0].local_stats.push_back(
1776       cricket::SsrcReceiverInfo());
1777   voice_media_info.receivers[0].local_stats[0].ssrc = 1;
1778   voice_media_info.receivers[0].packets_lost = -1;  // Signed per RFC3550
1779   voice_media_info.receivers[0].packets_rcvd = 2;
1780   voice_media_info.receivers[0].fec_packets_discarded = 5566;
1781   voice_media_info.receivers[0].fec_packets_received = 6677;
1782   voice_media_info.receivers[0].payload_bytes_rcvd = 3;
1783   voice_media_info.receivers[0].header_and_padding_bytes_rcvd = 4;
1784   voice_media_info.receivers[0].codec_payload_type = 42;
1785   voice_media_info.receivers[0].jitter_ms = 4500;
1786   voice_media_info.receivers[0].jitter_buffer_delay_seconds = 1.0;
1787   voice_media_info.receivers[0].jitter_buffer_emitted_count = 2;
1788   voice_media_info.receivers[0].total_samples_received = 3;
1789   voice_media_info.receivers[0].concealed_samples = 4;
1790   voice_media_info.receivers[0].silent_concealed_samples = 5;
1791   voice_media_info.receivers[0].concealment_events = 6;
1792   voice_media_info.receivers[0].inserted_samples_for_deceleration = 7;
1793   voice_media_info.receivers[0].removed_samples_for_acceleration = 8;
1794   voice_media_info.receivers[0].audio_level = 14442;  // [0,32767]
1795   voice_media_info.receivers[0].total_output_energy = 10.0;
1796   voice_media_info.receivers[0].total_output_duration = 11.0;
1797 
1798   voice_media_info.receivers[0].last_packet_received_timestamp_ms =
1799       absl::nullopt;
1800 
1801   RtpCodecParameters codec_parameters;
1802   codec_parameters.payload_type = 42;
1803   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1804   codec_parameters.name = "dummy";
1805   codec_parameters.clock_rate = 0;
1806   voice_media_info.receive_codecs.insert(
1807       std::make_pair(codec_parameters.payload_type, codec_parameters));
1808 
1809   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
1810   voice_media_channel->SetStats(voice_media_info);
1811   stats_->SetupRemoteTrackAndReceiver(
1812       cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1);
1813 
1814   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1815 
1816   auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1817   ASSERT_EQ(1U, stats_of_track_type.size());
1818 
1819   RTCInboundRTPStreamStats expected_audio("RTCInboundRTPAudioStream_1",
1820                                           report->timestamp_us());
1821   expected_audio.ssrc = 1;
1822   expected_audio.is_remote = false;
1823   expected_audio.media_type = "audio";
1824   expected_audio.kind = "audio";
1825   expected_audio.track_id = stats_of_track_type[0]->id();
1826   expected_audio.transport_id = "RTCTransport_TransportName_1";
1827   expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42";
1828   expected_audio.packets_received = 2;
1829   expected_audio.fec_packets_discarded = 5566;
1830   expected_audio.fec_packets_received = 6677;
1831   expected_audio.bytes_received = 3;
1832   expected_audio.header_bytes_received = 4;
1833   expected_audio.packets_lost = -1;
1834   // |expected_audio.last_packet_received_timestamp| should be undefined.
1835   expected_audio.jitter = 4.5;
1836   expected_audio.jitter_buffer_delay = 1.0;
1837   expected_audio.jitter_buffer_emitted_count = 2;
1838   expected_audio.total_samples_received = 3;
1839   expected_audio.concealed_samples = 4;
1840   expected_audio.silent_concealed_samples = 5;
1841   expected_audio.concealment_events = 6;
1842   expected_audio.inserted_samples_for_deceleration = 7;
1843   expected_audio.removed_samples_for_acceleration = 8;
1844   expected_audio.audio_level = 14442.0 / 32767.0;  // [0,1]
1845   expected_audio.total_audio_energy = 10.0;
1846   expected_audio.total_samples_duration = 11.0;
1847 
1848   ASSERT_TRUE(report->Get(expected_audio.id()));
1849   EXPECT_EQ(
1850       report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1851       expected_audio);
1852 
1853   // Set previously undefined values and "GetStats" again.
1854   voice_media_info.receivers[0].last_packet_received_timestamp_ms = 3000;
1855   expected_audio.last_packet_received_timestamp = 3.0;
1856   voice_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 4567;
1857   expected_audio.estimated_playout_timestamp = 4567;
1858   voice_media_channel->SetStats(voice_media_info);
1859 
1860   report = stats_->GetFreshStatsReport();
1861 
1862   ASSERT_TRUE(report->Get(expected_audio.id()));
1863   EXPECT_EQ(
1864       report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1865       expected_audio);
1866   EXPECT_TRUE(report->Get(*expected_audio.track_id));
1867   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1868   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
1869 }
1870 
TEST_F(RTCStatsCollectorTest,CollectRTCInboundRTPStreamStats_Video)1871 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
1872   cricket::VideoMediaInfo video_media_info;
1873 
1874   video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1875   video_media_info.receivers[0].local_stats.push_back(
1876       cricket::SsrcReceiverInfo());
1877   video_media_info.receivers[0].local_stats[0].ssrc = 1;
1878   video_media_info.receivers[0].packets_rcvd = 2;
1879   video_media_info.receivers[0].packets_lost = 42;
1880   video_media_info.receivers[0].payload_bytes_rcvd = 3;
1881   video_media_info.receivers[0].header_and_padding_bytes_rcvd = 12;
1882   video_media_info.receivers[0].codec_payload_type = 42;
1883   video_media_info.receivers[0].firs_sent = 5;
1884   video_media_info.receivers[0].plis_sent = 6;
1885   video_media_info.receivers[0].nacks_sent = 7;
1886   video_media_info.receivers[0].frames_received = 8;
1887   video_media_info.receivers[0].frames_decoded = 9;
1888   video_media_info.receivers[0].key_frames_decoded = 3;
1889   video_media_info.receivers[0].frames_dropped = 13;
1890   video_media_info.receivers[0].qp_sum = absl::nullopt;
1891   video_media_info.receivers[0].total_decode_time_ms = 9000;
1892   video_media_info.receivers[0].total_inter_frame_delay = 0.123;
1893   video_media_info.receivers[0].total_squared_inter_frame_delay = 0.00456;
1894 
1895   video_media_info.receivers[0].last_packet_received_timestamp_ms =
1896       absl::nullopt;
1897   video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
1898   video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms =
1899       absl::nullopt;
1900   video_media_info.receivers[0].decoder_implementation_name = "";
1901 
1902   RtpCodecParameters codec_parameters;
1903   codec_parameters.payload_type = 42;
1904   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1905   codec_parameters.name = "dummy";
1906   codec_parameters.clock_rate = 0;
1907   video_media_info.receive_codecs.insert(
1908       std::make_pair(codec_parameters.payload_type, codec_parameters));
1909 
1910   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
1911   video_media_channel->SetStats(video_media_info);
1912   stats_->SetupRemoteTrackAndReceiver(
1913       cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
1914 
1915   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1916 
1917   RTCInboundRTPStreamStats expected_video("RTCInboundRTPVideoStream_1",
1918                                           report->timestamp_us());
1919   expected_video.ssrc = 1;
1920   expected_video.is_remote = false;
1921   expected_video.media_type = "video";
1922   expected_video.kind = "video";
1923   expected_video.track_id = IdForType<RTCMediaStreamTrackStats>(report);
1924   expected_video.transport_id = "RTCTransport_TransportName_1";
1925   expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42";
1926   expected_video.fir_count = 5;
1927   expected_video.pli_count = 6;
1928   expected_video.nack_count = 7;
1929   expected_video.packets_received = 2;
1930   expected_video.bytes_received = 3;
1931   expected_video.header_bytes_received = 12;
1932   expected_video.packets_lost = 42;
1933   expected_video.frames_received = 8;
1934   expected_video.frames_decoded = 9;
1935   expected_video.key_frames_decoded = 3;
1936   expected_video.frames_dropped = 13;
1937   // |expected_video.qp_sum| should be undefined.
1938   expected_video.total_decode_time = 9.0;
1939   expected_video.total_inter_frame_delay = 0.123;
1940   expected_video.total_squared_inter_frame_delay = 0.00456;
1941   // |expected_video.last_packet_received_timestamp| should be undefined.
1942   // |expected_video.content_type| should be undefined.
1943   // |expected_video.decoder_implementation| should be undefined.
1944 
1945   ASSERT_TRUE(report->Get(expected_video.id()));
1946   EXPECT_EQ(
1947       report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1948       expected_video);
1949 
1950   // Set previously undefined values and "GetStats" again.
1951   video_media_info.receivers[0].qp_sum = 9;
1952   expected_video.qp_sum = 9;
1953   video_media_info.receivers[0].last_packet_received_timestamp_ms = 1000;
1954   expected_video.last_packet_received_timestamp = 1.0;
1955   video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
1956   expected_video.content_type = "screenshare";
1957   video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 1234;
1958   expected_video.estimated_playout_timestamp = 1234;
1959   video_media_info.receivers[0].decoder_implementation_name = "libfoodecoder";
1960   expected_video.decoder_implementation = "libfoodecoder";
1961   video_media_channel->SetStats(video_media_info);
1962 
1963   report = stats_->GetFreshStatsReport();
1964 
1965   ASSERT_TRUE(report->Get(expected_video.id()));
1966   EXPECT_EQ(
1967       report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1968       expected_video);
1969   EXPECT_TRUE(report->Get(*expected_video.track_id));
1970   EXPECT_TRUE(report->Get(*expected_video.transport_id));
1971   EXPECT_TRUE(report->Get(*expected_video.codec_id));
1972 }
1973 
TEST_F(RTCStatsCollectorTest,CollectRTCOutboundRTPStreamStats_Audio)1974 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
1975   cricket::VoiceMediaInfo voice_media_info;
1976 
1977   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1978   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1979   voice_media_info.senders[0].local_stats[0].ssrc = 1;
1980   voice_media_info.senders[0].packets_sent = 2;
1981   voice_media_info.senders[0].retransmitted_packets_sent = 20;
1982   voice_media_info.senders[0].payload_bytes_sent = 3;
1983   voice_media_info.senders[0].header_and_padding_bytes_sent = 12;
1984   voice_media_info.senders[0].retransmitted_bytes_sent = 30;
1985   voice_media_info.senders[0].codec_payload_type = 42;
1986 
1987   RtpCodecParameters codec_parameters;
1988   codec_parameters.payload_type = 42;
1989   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1990   codec_parameters.name = "dummy";
1991   codec_parameters.clock_rate = 0;
1992   voice_media_info.send_codecs.insert(
1993       std::make_pair(codec_parameters.payload_type, codec_parameters));
1994 
1995   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
1996   voice_media_channel->SetStats(voice_media_info);
1997   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
1998                                    "LocalAudioTrackID", 1, true,
1999                                    /*attachment_id=*/50);
2000 
2001   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2002 
2003   RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
2004                                            report->timestamp_us());
2005   expected_audio.media_source_id = "RTCAudioSource_50";
2006   // |expected_audio.remote_id| should be undefined.
2007   expected_audio.ssrc = 1;
2008   expected_audio.is_remote = false;
2009   expected_audio.media_type = "audio";
2010   expected_audio.kind = "audio";
2011   expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
2012   expected_audio.transport_id = "RTCTransport_TransportName_1";
2013   expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
2014   expected_audio.packets_sent = 2;
2015   expected_audio.retransmitted_packets_sent = 20;
2016   expected_audio.bytes_sent = 3;
2017   expected_audio.header_bytes_sent = 12;
2018   expected_audio.retransmitted_bytes_sent = 30;
2019 
2020   ASSERT_TRUE(report->Get(expected_audio.id()));
2021   EXPECT_EQ(
2022       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2023       expected_audio);
2024 
2025   ASSERT_TRUE(report->Get(expected_audio.id()));
2026   EXPECT_EQ(
2027       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2028       expected_audio);
2029   EXPECT_TRUE(report->Get(*expected_audio.track_id));
2030   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2031   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2032 }
2033 
TEST_F(RTCStatsCollectorTest,CollectRTCOutboundRTPStreamStats_Video)2034 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
2035   cricket::VideoMediaInfo video_media_info;
2036 
2037   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2038   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2039   video_media_info.senders[0].local_stats[0].ssrc = 1;
2040   video_media_info.senders[0].firs_rcvd = 2;
2041   video_media_info.senders[0].plis_rcvd = 3;
2042   video_media_info.senders[0].nacks_rcvd = 4;
2043   video_media_info.senders[0].packets_sent = 5;
2044   video_media_info.senders[0].retransmitted_packets_sent = 50;
2045   video_media_info.senders[0].payload_bytes_sent = 6;
2046   video_media_info.senders[0].header_and_padding_bytes_sent = 12;
2047   video_media_info.senders[0].retransmitted_bytes_sent = 60;
2048   video_media_info.senders[0].codec_payload_type = 42;
2049   video_media_info.senders[0].frames_encoded = 8;
2050   video_media_info.senders[0].key_frames_encoded = 3;
2051   video_media_info.senders[0].total_encode_time_ms = 9000;
2052   video_media_info.senders[0].total_encoded_bytes_target = 1234;
2053   video_media_info.senders[0].total_packet_send_delay_ms = 10000;
2054   video_media_info.senders[0].quality_limitation_reason =
2055       QualityLimitationReason::kBandwidth;
2056   video_media_info.senders[0].quality_limitation_resolution_changes = 56u;
2057   video_media_info.senders[0].qp_sum = absl::nullopt;
2058   video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
2059   video_media_info.senders[0].encoder_implementation_name = "";
2060   video_media_info.senders[0].send_frame_width = 200;
2061   video_media_info.senders[0].send_frame_height = 100;
2062   video_media_info.senders[0].framerate_sent = 10;
2063   video_media_info.senders[0].frames_sent = 5;
2064   video_media_info.senders[0].huge_frames_sent = 2;
2065   video_media_info.aggregated_senders.push_back(video_media_info.senders[0]);
2066   RtpCodecParameters codec_parameters;
2067   codec_parameters.payload_type = 42;
2068   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2069   codec_parameters.name = "dummy";
2070   codec_parameters.clock_rate = 0;
2071   video_media_info.send_codecs.insert(
2072       std::make_pair(codec_parameters.payload_type, codec_parameters));
2073 
2074   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2075   video_media_channel->SetStats(video_media_info);
2076   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
2077                                    "LocalVideoTrackID", 1, true,
2078                                    /*attachment_id=*/50);
2079 
2080   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2081 
2082   auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
2083   ASSERT_EQ(1U, stats_of_my_type.size());
2084   auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
2085   ASSERT_EQ(1U, stats_of_track_type.size());
2086 
2087   RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
2088                                            report->timestamp_us());
2089   expected_video.media_source_id = "RTCVideoSource_50";
2090   // |expected_video.remote_id| should be undefined.
2091   expected_video.ssrc = 1;
2092   expected_video.is_remote = false;
2093   expected_video.media_type = "video";
2094   expected_video.kind = "video";
2095   expected_video.track_id = stats_of_track_type[0]->id();
2096   expected_video.transport_id = "RTCTransport_TransportName_1";
2097   expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42";
2098   expected_video.fir_count = 2;
2099   expected_video.pli_count = 3;
2100   expected_video.nack_count = 4;
2101   expected_video.packets_sent = 5;
2102   expected_video.retransmitted_packets_sent = 50;
2103   expected_video.bytes_sent = 6;
2104   expected_video.header_bytes_sent = 12;
2105   expected_video.retransmitted_bytes_sent = 60;
2106   expected_video.frames_encoded = 8;
2107   expected_video.key_frames_encoded = 3;
2108   expected_video.total_encode_time = 9.0;
2109   expected_video.total_encoded_bytes_target = 1234;
2110   expected_video.total_packet_send_delay = 10.0;
2111   expected_video.quality_limitation_reason = "bandwidth";
2112   expected_video.quality_limitation_resolution_changes = 56u;
2113   expected_video.frame_width = 200u;
2114   expected_video.frame_height = 100u;
2115   expected_video.frames_per_second = 10.0;
2116   expected_video.frames_sent = 5;
2117   expected_video.huge_frames_sent = 2;
2118   // |expected_video.content_type| should be undefined.
2119   // |expected_video.qp_sum| should be undefined.
2120   // |expected_video.encoder_implementation| should be undefined.
2121   ASSERT_TRUE(report->Get(expected_video.id()));
2122 
2123   EXPECT_EQ(
2124       report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2125       expected_video);
2126 
2127   // Set previously undefined values and "GetStats" again.
2128   video_media_info.senders[0].qp_sum = 9;
2129   expected_video.qp_sum = 9;
2130   video_media_info.senders[0].content_type = VideoContentType::SCREENSHARE;
2131   expected_video.content_type = "screenshare";
2132   video_media_info.senders[0].encoder_implementation_name = "libfooencoder";
2133   video_media_info.aggregated_senders[0] = video_media_info.senders[0];
2134   expected_video.encoder_implementation = "libfooencoder";
2135   video_media_channel->SetStats(video_media_info);
2136 
2137   report = stats_->GetFreshStatsReport();
2138 
2139   ASSERT_TRUE(report->Get(expected_video.id()));
2140   EXPECT_EQ(
2141       report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2142       expected_video);
2143   EXPECT_TRUE(report->Get(*expected_video.track_id));
2144   EXPECT_TRUE(report->Get(*expected_video.transport_id));
2145   EXPECT_TRUE(report->Get(*expected_video.codec_id));
2146 }
2147 
TEST_F(RTCStatsCollectorTest,CollectRTCTransportStats)2148 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
2149   const char kTransportName[] = "transport";
2150 
2151   pc_->AddVoiceChannel("audio", kTransportName);
2152 
2153   std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2154       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2155                           cricket::LOCAL_PORT_TYPE, 42);
2156   std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2157       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2158                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2159                           42);
2160   std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
2161       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2162                           cricket::LOCAL_PORT_TYPE, 42);
2163   std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2164       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2165                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2166                           42);
2167 
2168   cricket::ConnectionInfo rtp_connection_info;
2169   rtp_connection_info.best_connection = false;
2170   rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2171   rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
2172   rtp_connection_info.sent_total_bytes = 42;
2173   rtp_connection_info.recv_total_bytes = 1337;
2174   rtp_connection_info.sent_total_packets = 3;
2175   rtp_connection_info.sent_discarded_packets = 2;
2176   rtp_connection_info.packets_received = 4;
2177   cricket::TransportChannelStats rtp_transport_channel_stats;
2178   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2179   rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2180       rtp_connection_info);
2181   rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
2182   rtp_transport_channel_stats.ice_transport_stats
2183       .selected_candidate_pair_changes = 1;
2184   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
2185 
2186   // Get stats without RTCP, an active connection or certificates.
2187   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2188 
2189   RTCTransportStats expected_rtp_transport(
2190       "RTCTransport_transport_" +
2191           rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
2192       report->timestamp_us());
2193   expected_rtp_transport.bytes_sent = 42;
2194   expected_rtp_transport.packets_sent = 1;
2195   expected_rtp_transport.bytes_received = 1337;
2196   expected_rtp_transport.packets_received = 4;
2197   expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
2198   expected_rtp_transport.selected_candidate_pair_changes = 1;
2199 
2200   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2201   EXPECT_EQ(
2202       expected_rtp_transport,
2203       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2204 
2205   cricket::ConnectionInfo rtcp_connection_info;
2206   rtcp_connection_info.best_connection = false;
2207   rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
2208   rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
2209   rtcp_connection_info.sent_total_bytes = 1337;
2210   rtcp_connection_info.recv_total_bytes = 42;
2211   rtcp_connection_info.sent_total_packets = 3;
2212   rtcp_connection_info.sent_discarded_packets = 2;
2213   rtcp_connection_info.packets_received = 4;
2214   cricket::TransportChannelStats rtcp_transport_channel_stats;
2215   rtcp_transport_channel_stats.component =
2216       cricket::ICE_CANDIDATE_COMPONENT_RTCP;
2217   rtcp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2218       rtcp_connection_info);
2219   rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTING;
2220   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2221                                           rtcp_transport_channel_stats});
2222 
2223   // Get stats with RTCP and without an active connection or certificates.
2224   report = stats_->GetFreshStatsReport();
2225 
2226   RTCTransportStats expected_rtcp_transport(
2227       "RTCTransport_transport_" +
2228           rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
2229       report->timestamp_us());
2230   expected_rtcp_transport.bytes_sent = 1337;
2231   expected_rtcp_transport.packets_sent = 1;
2232   expected_rtcp_transport.bytes_received = 42;
2233   expected_rtcp_transport.packets_received = 4;
2234   expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
2235   expected_rtcp_transport.selected_candidate_pair_changes = 0;
2236 
2237   expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
2238   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2239   EXPECT_EQ(
2240       expected_rtp_transport,
2241       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2242   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
2243   EXPECT_EQ(
2244       expected_rtcp_transport,
2245       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
2246 
2247   // Get stats with an active connection (selected candidate pair).
2248   rtcp_transport_channel_stats.ice_transport_stats.connection_infos[0]
2249       .best_connection = true;
2250   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2251                                           rtcp_transport_channel_stats});
2252 
2253   report = stats_->GetFreshStatsReport();
2254 
2255   expected_rtcp_transport.selected_candidate_pair_id =
2256       "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" +
2257       rtcp_remote_candidate->id();
2258 
2259   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2260   EXPECT_EQ(
2261       expected_rtp_transport,
2262       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2263   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
2264   EXPECT_EQ(
2265       expected_rtcp_transport,
2266       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
2267 
2268   // Get stats with certificates.
2269   std::unique_ptr<CertificateInfo> local_certinfo =
2270       CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
2271   pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
2272   std::unique_ptr<CertificateInfo> remote_certinfo =
2273       CreateFakeCertificateAndInfoFromDers(
2274           {"(remote) local", "(remote) chain"});
2275   pc_->SetRemoteCertChain(
2276       kTransportName,
2277       remote_certinfo->certificate->GetSSLCertificateChain().Clone());
2278 
2279   report = stats_->GetFreshStatsReport();
2280 
2281   expected_rtp_transport.local_certificate_id =
2282       "RTCCertificate_" + local_certinfo->fingerprints[0];
2283   expected_rtp_transport.remote_certificate_id =
2284       "RTCCertificate_" + remote_certinfo->fingerprints[0];
2285 
2286   expected_rtcp_transport.local_certificate_id =
2287       *expected_rtp_transport.local_certificate_id;
2288   expected_rtcp_transport.remote_certificate_id =
2289       *expected_rtp_transport.remote_certificate_id;
2290 
2291   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2292   EXPECT_EQ(
2293       expected_rtp_transport,
2294       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2295   ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
2296   EXPECT_EQ(
2297       expected_rtcp_transport,
2298       report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
2299 }
2300 
TEST_F(RTCStatsCollectorTest,CollectRTCTransportStatsWithCrypto)2301 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) {
2302   const char kTransportName[] = "transport";
2303 
2304   pc_->AddVoiceChannel("audio", kTransportName);
2305 
2306   std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2307       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2308                           cricket::LOCAL_PORT_TYPE, 42);
2309   std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2310       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2311                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2312                           42);
2313   std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
2314       CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2315                           cricket::LOCAL_PORT_TYPE, 42);
2316   std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2317       CreateFakeCandidate("42.42.42.42", 42, "protocol",
2318                           rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2319                           42);
2320 
2321   cricket::ConnectionInfo rtp_connection_info;
2322   rtp_connection_info.best_connection = false;
2323   rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2324   rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
2325   rtp_connection_info.sent_total_bytes = 42;
2326   rtp_connection_info.recv_total_bytes = 1337;
2327   rtp_connection_info.sent_total_packets = 3;
2328   rtp_connection_info.sent_discarded_packets = 2;
2329   rtp_connection_info.packets_received = 4;
2330   cricket::TransportChannelStats rtp_transport_channel_stats;
2331   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2332   rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back(
2333       rtp_connection_info);
2334   // The state must be connected in order for crypto parameters to show up.
2335   rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTED;
2336   rtp_transport_channel_stats.ice_transport_stats
2337       .selected_candidate_pair_changes = 1;
2338   rtp_transport_channel_stats.ssl_version_bytes = 0x0203;
2339   // 0x2F is TLS_RSA_WITH_AES_128_CBC_SHA according to IANA
2340   rtp_transport_channel_stats.ssl_cipher_suite = 0x2F;
2341   rtp_transport_channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80;
2342   pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
2343 
2344   // Get stats
2345   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2346 
2347   RTCTransportStats expected_rtp_transport(
2348       "RTCTransport_transport_" +
2349           rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
2350       report->timestamp_us());
2351   expected_rtp_transport.bytes_sent = 42;
2352   expected_rtp_transport.packets_sent = 1;
2353   expected_rtp_transport.bytes_received = 1337;
2354   expected_rtp_transport.packets_received = 4;
2355   expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected;
2356   expected_rtp_transport.selected_candidate_pair_changes = 1;
2357   // Crypto parameters
2358   expected_rtp_transport.tls_version = "0203";
2359   expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA";
2360   expected_rtp_transport.srtp_cipher = "AES_CM_128_HMAC_SHA1_80";
2361 
2362   ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
2363   EXPECT_EQ(
2364       expected_rtp_transport,
2365       report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
2366 }
2367 
TEST_F(RTCStatsCollectorTest,CollectNoStreamRTCOutboundRTPStreamStats_Audio)2368 TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
2369   cricket::VoiceMediaInfo voice_media_info;
2370 
2371   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2372   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2373   voice_media_info.senders[0].local_stats[0].ssrc = 1;
2374   voice_media_info.senders[0].packets_sent = 2;
2375   voice_media_info.senders[0].retransmitted_packets_sent = 20;
2376   voice_media_info.senders[0].payload_bytes_sent = 3;
2377   voice_media_info.senders[0].header_and_padding_bytes_sent = 4;
2378   voice_media_info.senders[0].retransmitted_bytes_sent = 30;
2379   voice_media_info.senders[0].codec_payload_type = 42;
2380 
2381   RtpCodecParameters codec_parameters;
2382   codec_parameters.payload_type = 42;
2383   codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2384   codec_parameters.name = "dummy";
2385   codec_parameters.clock_rate = 0;
2386   voice_media_info.send_codecs.insert(
2387       std::make_pair(codec_parameters.payload_type, codec_parameters));
2388 
2389   // Emulates the case where AddTrack is used without an associated MediaStream
2390   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
2391   voice_media_channel->SetStats(voice_media_info);
2392   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
2393                                    "LocalAudioTrackID", 1, false,
2394                                    /*attachment_id=*/50);
2395 
2396   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2397 
2398   RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
2399                                            report->timestamp_us());
2400   expected_audio.media_source_id = "RTCAudioSource_50";
2401   expected_audio.ssrc = 1;
2402   expected_audio.is_remote = false;
2403   expected_audio.media_type = "audio";
2404   expected_audio.kind = "audio";
2405   expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
2406   expected_audio.transport_id = "RTCTransport_TransportName_1";
2407   expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
2408   expected_audio.packets_sent = 2;
2409   expected_audio.retransmitted_packets_sent = 20;
2410   expected_audio.bytes_sent = 3;
2411   expected_audio.header_bytes_sent = 4;
2412   expected_audio.retransmitted_bytes_sent = 30;
2413 
2414   ASSERT_TRUE(report->Get(expected_audio.id()));
2415   EXPECT_EQ(
2416       report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2417       expected_audio);
2418   EXPECT_TRUE(report->Get(*expected_audio.track_id));
2419   EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2420   EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2421 }
2422 
TEST_F(RTCStatsCollectorTest,RTCAudioSourceStatsCollectedForSenderWithTrack)2423 TEST_F(RTCStatsCollectorTest, RTCAudioSourceStatsCollectedForSenderWithTrack) {
2424   const uint32_t kSsrc = 4;
2425   const int kAttachmentId = 42;
2426 
2427   cricket::VoiceMediaInfo voice_media_info;
2428   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2429   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2430   voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2431   voice_media_info.senders[0].audio_level = 32767;  // [0,32767]
2432   voice_media_info.senders[0].total_input_energy = 2.0;
2433   voice_media_info.senders[0].total_input_duration = 3.0;
2434   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
2435   voice_media_channel->SetStats(voice_media_info);
2436   stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
2437                                    "LocalAudioTrackID", kSsrc, false,
2438                                    kAttachmentId);
2439 
2440   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2441 
2442   RTCAudioSourceStats expected_audio("RTCAudioSource_42",
2443                                      report->timestamp_us());
2444   expected_audio.track_identifier = "LocalAudioTrackID";
2445   expected_audio.kind = "audio";
2446   expected_audio.audio_level = 1.0;  // [0,1]
2447   expected_audio.total_audio_energy = 2.0;
2448   expected_audio.total_samples_duration = 3.0;
2449 
2450   ASSERT_TRUE(report->Get(expected_audio.id()));
2451   EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
2452             expected_audio);
2453 }
2454 
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsCollectedForSenderWithTrack)2455 TEST_F(RTCStatsCollectorTest, RTCVideoSourceStatsCollectedForSenderWithTrack) {
2456   const uint32_t kSsrc = 4;
2457   const int kAttachmentId = 42;
2458   const int kVideoSourceWidth = 12;
2459   const int kVideoSourceHeight = 34;
2460 
2461   cricket::VideoMediaInfo video_media_info;
2462   video_media_info.aggregated_senders.push_back(cricket::VideoSenderInfo());
2463   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2464   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2465   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2466   video_media_info.senders[0].framerate_input = 29;
2467   video_media_info.aggregated_senders[0].local_stats.push_back(
2468       cricket::SsrcSenderInfo());
2469   video_media_info.aggregated_senders[0].local_stats[0].ssrc = kSsrc;
2470   video_media_info.aggregated_senders[0].framerate_input = 29;
2471   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2472   video_media_channel->SetStats(video_media_info);
2473 
2474   auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2475                                                            kVideoSourceHeight);
2476   auto video_track = FakeVideoTrackForStats::Create(
2477       "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2478   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2479       cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
2480   pc_->AddSender(sender);
2481 
2482   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2483 
2484   RTCVideoSourceStats expected_video("RTCVideoSource_42",
2485                                      report->timestamp_us());
2486   expected_video.track_identifier = "LocalVideoTrackID";
2487   expected_video.kind = "video";
2488   expected_video.width = kVideoSourceWidth;
2489   expected_video.height = kVideoSourceHeight;
2490   // |expected_video.frames| is expected to be undefined because it is not set.
2491   // TODO(hbos): When implemented, set its expected value here.
2492   expected_video.frames_per_second = 29;
2493 
2494   ASSERT_TRUE(report->Get(expected_video.id()));
2495   EXPECT_EQ(report->Get(expected_video.id())->cast_to<RTCVideoSourceStats>(),
2496             expected_video);
2497 }
2498 
2499 // This test exercises the current behavior and code path, but the correct
2500 // behavior is to report frame rate even if we have no SSRC.
2501 // TODO(hbos): When we know the frame rate even if we have no SSRC, update the
2502 // expectations of this test.
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc)2503 TEST_F(RTCStatsCollectorTest,
2504        RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc) {
2505   // TODO(https://crbug.com/webrtc/8694): When 0 is no longer a magic value for
2506   // "none", update this test.
2507   const uint32_t kNoSsrc = 0;
2508   const int kAttachmentId = 42;
2509   const int kVideoSourceWidth = 12;
2510   const int kVideoSourceHeight = 34;
2511 
2512   cricket::VideoMediaInfo video_media_info;
2513   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2514   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2515   video_media_info.senders[0].framerate_input = 29;
2516   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2517   video_media_channel->SetStats(video_media_info);
2518 
2519   auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2520                                                            kVideoSourceHeight);
2521   auto video_track = FakeVideoTrackForStats::Create(
2522       "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2523   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2524       cricket::MEDIA_TYPE_VIDEO, video_track, kNoSsrc, kAttachmentId, {});
2525   pc_->AddSender(sender);
2526 
2527   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2528   ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2529   auto video_stats =
2530       report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2531   EXPECT_FALSE(video_stats.frames_per_second.is_defined());
2532 }
2533 
2534 // The track not having a source is not expected to be true in practise, but
2535 // this is true in some tests relying on fakes. This test covers that code path.
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource)2536 TEST_F(RTCStatsCollectorTest,
2537        RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource) {
2538   const uint32_t kSsrc = 4;
2539   const int kAttachmentId = 42;
2540 
2541   cricket::VideoMediaInfo video_media_info;
2542   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2543   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2544   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2545   video_media_info.senders[0].framerate_input = 29;
2546   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2547   video_media_channel->SetStats(video_media_info);
2548 
2549   auto video_track = FakeVideoTrackForStats::Create(
2550       "LocalVideoTrackID", MediaStreamTrackInterface::kLive,
2551       /*source=*/nullptr);
2552   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2553       cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
2554   pc_->AddSender(sender);
2555 
2556   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2557   ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2558   auto video_stats =
2559       report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2560   EXPECT_FALSE(video_stats.width.is_defined());
2561   EXPECT_FALSE(video_stats.height.is_defined());
2562 }
2563 
TEST_F(RTCStatsCollectorTest,RTCAudioSourceStatsNotCollectedForSenderWithoutTrack)2564 TEST_F(RTCStatsCollectorTest,
2565        RTCAudioSourceStatsNotCollectedForSenderWithoutTrack) {
2566   const uint32_t kSsrc = 4;
2567   const int kAttachmentId = 42;
2568 
2569   cricket::VoiceMediaInfo voice_media_info;
2570   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2571   voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2572   voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2573   auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
2574   voice_media_channel->SetStats(voice_media_info);
2575   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2576       cricket::MEDIA_TYPE_AUDIO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
2577   pc_->AddSender(sender);
2578 
2579   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2580   EXPECT_FALSE(report->Get("RTCAudioSource_42"));
2581 }
2582 
2583 // Parameterized tests on cricket::MediaType (audio or video).
2584 class RTCStatsCollectorTestWithParamKind
2585     : public RTCStatsCollectorTest,
2586       public ::testing::WithParamInterface<cricket::MediaType> {
2587  public:
RTCStatsCollectorTestWithParamKind()2588   RTCStatsCollectorTestWithParamKind() : media_type_(GetParam()) {
2589     RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
2590                media_type_ == cricket::MEDIA_TYPE_VIDEO);
2591   }
2592 
MediaTypeUpperCase() const2593   std::string MediaTypeUpperCase() const {
2594     switch (media_type_) {
2595       case cricket::MEDIA_TYPE_AUDIO:
2596         return "Audio";
2597       case cricket::MEDIA_TYPE_VIDEO:
2598         return "Video";
2599       case cricket::MEDIA_TYPE_DATA:
2600       case cricket::MEDIA_TYPE_UNSUPPORTED:
2601         RTC_NOTREACHED();
2602         return "";
2603     }
2604   }
2605 
MediaTypeLowerCase() const2606   std::string MediaTypeLowerCase() const {
2607     std::string str = MediaTypeUpperCase();
2608     std::transform(str.begin(), str.end(), str.begin(), ::tolower);
2609     return str;
2610   }
2611 
2612   // Adds a sender and channel of the appropriate kind, creating a sender info
2613   // 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)2614   void AddSenderInfoAndMediaChannel(
2615       std::string transport_name,
2616       const std::vector<ReportBlockData>& report_block_datas,
2617       absl::optional<RtpCodecParameters> codec) {
2618     switch (media_type_) {
2619       case cricket::MEDIA_TYPE_AUDIO: {
2620         cricket::VoiceMediaInfo voice_media_info;
2621         for (const auto& report_block_data : report_block_datas) {
2622           cricket::VoiceSenderInfo sender;
2623           sender.local_stats.push_back(cricket::SsrcSenderInfo());
2624           sender.local_stats[0].ssrc =
2625               report_block_data.report_block().source_ssrc;
2626           if (codec.has_value()) {
2627             sender.codec_payload_type = codec->payload_type;
2628             voice_media_info.send_codecs.insert(
2629                 std::make_pair(codec->payload_type, *codec));
2630           }
2631           sender.report_block_datas.push_back(report_block_data);
2632           voice_media_info.senders.push_back(sender);
2633         }
2634         auto* voice_media_channel = pc_->AddVoiceChannel("mid", transport_name);
2635         voice_media_channel->SetStats(voice_media_info);
2636         return;
2637       }
2638       case cricket::MEDIA_TYPE_VIDEO: {
2639         cricket::VideoMediaInfo video_media_info;
2640         for (const auto& report_block_data : report_block_datas) {
2641           cricket::VideoSenderInfo sender;
2642           sender.local_stats.push_back(cricket::SsrcSenderInfo());
2643           sender.local_stats[0].ssrc =
2644               report_block_data.report_block().source_ssrc;
2645           if (codec.has_value()) {
2646             sender.codec_payload_type = codec->payload_type;
2647             video_media_info.send_codecs.insert(
2648                 std::make_pair(codec->payload_type, *codec));
2649           }
2650           sender.report_block_datas.push_back(report_block_data);
2651           video_media_info.aggregated_senders.push_back(sender);
2652           video_media_info.senders.push_back(sender);
2653         }
2654         auto* video_media_channel = pc_->AddVideoChannel("mid", transport_name);
2655         video_media_channel->SetStats(video_media_info);
2656         return;
2657       }
2658       case cricket::MEDIA_TYPE_DATA:
2659       case cricket::MEDIA_TYPE_UNSUPPORTED:
2660         RTC_NOTREACHED();
2661     }
2662   }
2663 
2664  protected:
2665   cricket::MediaType media_type_;
2666 };
2667 
2668 // Verifies RTCRemoteInboundRtpStreamStats members that don't require
2669 // RTCCodecStats (codecId, jitter) and without setting up an RTCP transport.
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsCollectedFromReportBlock)2670 TEST_P(RTCStatsCollectorTestWithParamKind,
2671        RTCRemoteInboundRtpStreamStatsCollectedFromReportBlock) {
2672   const int64_t kReportBlockTimestampUtcUs = 123456789;
2673   const int64_t kRoundTripTimeMs = 13000;
2674   const double kRoundTripTimeSeconds = 13.0;
2675 
2676   // The report block's timestamp cannot be from the future, set the fake clock
2677   // to match.
2678   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
2679   auto ssrcs = {12, 13};
2680   std::vector<ReportBlockData> report_block_datas;
2681   for (auto ssrc : ssrcs) {
2682     RTCPReportBlock report_block;
2683     // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
2684     // |source_ssrc|, "SSRC of the RTP packet sender".
2685     report_block.source_ssrc = ssrc;
2686     report_block.packets_lost = 7;
2687     ReportBlockData report_block_data;
2688     report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
2689     report_block_data.AddRoundTripTimeSample(1234);
2690     // Only the last sample should be exposed as the
2691     // |RTCRemoteInboundRtpStreamStats::round_trip_time|.
2692     report_block_data.AddRoundTripTimeSample(kRoundTripTimeMs);
2693     report_block_datas.push_back(report_block_data);
2694   }
2695   AddSenderInfoAndMediaChannel("TransportName", report_block_datas,
2696                                absl::nullopt);
2697 
2698   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2699   for (auto ssrc : ssrcs) {
2700     std::string stream_id = "Stream_" + std::to_string(ssrc);
2701     RTCRemoteInboundRtpStreamStats expected_remote_inbound_rtp(
2702         "RTCRemoteInboundRtp" + MediaTypeUpperCase() + stream_id,
2703         kReportBlockTimestampUtcUs);
2704     expected_remote_inbound_rtp.ssrc = ssrc;
2705     expected_remote_inbound_rtp.kind = MediaTypeLowerCase();
2706     expected_remote_inbound_rtp.transport_id =
2707         "RTCTransport_TransportName_1";  // 1 for RTP (we have no RTCP
2708                                          // transport)
2709     expected_remote_inbound_rtp.packets_lost = 7;
2710     expected_remote_inbound_rtp.local_id =
2711         "RTCOutboundRTP" + MediaTypeUpperCase() + stream_id;
2712     expected_remote_inbound_rtp.round_trip_time = kRoundTripTimeSeconds;
2713     // This test does not set up RTCCodecStats, so |codec_id| and |jitter| are
2714     // expected to be missing. These are tested separately.
2715 
2716     ASSERT_TRUE(report->Get(expected_remote_inbound_rtp.id()));
2717     EXPECT_EQ(report->Get(expected_remote_inbound_rtp.id())
2718                   ->cast_to<RTCRemoteInboundRtpStreamStats>(),
2719               expected_remote_inbound_rtp);
2720     EXPECT_TRUE(report->Get(*expected_remote_inbound_rtp.transport_id));
2721     ASSERT_TRUE(report->Get(*expected_remote_inbound_rtp.local_id));
2722     // Lookup works in both directions.
2723     EXPECT_EQ(*report->Get(*expected_remote_inbound_rtp.local_id)
2724                    ->cast_to<RTCOutboundRTPStreamStats>()
2725                    .remote_id,
2726               expected_remote_inbound_rtp.id());
2727   }
2728 }
2729 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithTimestampFromReportBlock)2730 TEST_P(RTCStatsCollectorTestWithParamKind,
2731        RTCRemoteInboundRtpStreamStatsWithTimestampFromReportBlock) {
2732   const int64_t kReportBlockTimestampUtcUs = 123456789;
2733   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
2734 
2735   RTCPReportBlock report_block;
2736   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
2737   // |source_ssrc|, "SSRC of the RTP packet sender".
2738   report_block.source_ssrc = 12;
2739   ReportBlockData report_block_data;
2740   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
2741 
2742   AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
2743                                absl::nullopt);
2744 
2745   // Advance time, it should be OK to have fresher reports than report blocks.
2746   fake_clock_.AdvanceTime(TimeDelta::Micros(1234));
2747 
2748   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2749 
2750   std::string remote_inbound_rtp_id =
2751       "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
2752   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
2753   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
2754                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
2755 
2756   // Even though the report time is different, the remote-inbound-rtp timestamp
2757   // is of the time that the report block was received.
2758   EXPECT_EQ(kReportBlockTimestampUtcUs + 1234, report->timestamp_us());
2759   EXPECT_EQ(kReportBlockTimestampUtcUs, remote_inbound_rtp.timestamp_us());
2760 }
2761 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithCodecBasedMembers)2762 TEST_P(RTCStatsCollectorTestWithParamKind,
2763        RTCRemoteInboundRtpStreamStatsWithCodecBasedMembers) {
2764   const int64_t kReportBlockTimestampUtcUs = 123456789;
2765   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
2766 
2767   RTCPReportBlock report_block;
2768   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
2769   // |source_ssrc|, "SSRC of the RTP packet sender".
2770   report_block.source_ssrc = 12;
2771   report_block.jitter = 5000;
2772   ReportBlockData report_block_data;
2773   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
2774 
2775   RtpCodecParameters codec;
2776   codec.payload_type = 3;
2777   codec.kind = media_type_;
2778   codec.clock_rate = 1000;
2779 
2780   AddSenderInfoAndMediaChannel("TransportName", {report_block_data}, codec);
2781 
2782   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2783 
2784   std::string remote_inbound_rtp_id =
2785       "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
2786   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
2787   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
2788                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
2789 
2790   EXPECT_TRUE(remote_inbound_rtp.codec_id.is_defined());
2791   EXPECT_TRUE(report->Get(*remote_inbound_rtp.codec_id));
2792 
2793   EXPECT_TRUE(remote_inbound_rtp.jitter.is_defined());
2794   // The jitter (in seconds) is the report block's jitter divided by the codec's
2795   // clock rate.
2796   EXPECT_EQ(5.0, *remote_inbound_rtp.jitter);
2797 }
2798 
TEST_P(RTCStatsCollectorTestWithParamKind,RTCRemoteInboundRtpStreamStatsWithRtcpTransport)2799 TEST_P(RTCStatsCollectorTestWithParamKind,
2800        RTCRemoteInboundRtpStreamStatsWithRtcpTransport) {
2801   const int64_t kReportBlockTimestampUtcUs = 123456789;
2802   fake_clock_.SetTime(Timestamp::Micros(kReportBlockTimestampUtcUs));
2803 
2804   RTCPReportBlock report_block;
2805   // The remote-inbound-rtp SSRC and the outbound-rtp SSRC is the same as the
2806   // |source_ssrc|, "SSRC of the RTP packet sender".
2807   report_block.source_ssrc = 12;
2808   ReportBlockData report_block_data;
2809   report_block_data.SetReportBlock(report_block, kReportBlockTimestampUtcUs);
2810 
2811   cricket::TransportChannelStats rtp_transport_channel_stats;
2812   rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2813   rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
2814   cricket::TransportChannelStats rtcp_transport_channel_stats;
2815   rtcp_transport_channel_stats.component =
2816       cricket::ICE_CANDIDATE_COMPONENT_RTCP;
2817   rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
2818   pc_->SetTransportStats("TransportName", {rtp_transport_channel_stats,
2819                                            rtcp_transport_channel_stats});
2820   AddSenderInfoAndMediaChannel("TransportName", {report_block_data},
2821                                absl::nullopt);
2822 
2823   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2824 
2825   std::string remote_inbound_rtp_id =
2826       "RTCRemoteInboundRtp" + MediaTypeUpperCase() + "Stream_12";
2827   ASSERT_TRUE(report->Get(remote_inbound_rtp_id));
2828   auto& remote_inbound_rtp = report->Get(remote_inbound_rtp_id)
2829                                  ->cast_to<RTCRemoteInboundRtpStreamStats>();
2830 
2831   EXPECT_TRUE(remote_inbound_rtp.transport_id.is_defined());
2832   EXPECT_EQ("RTCTransport_TransportName_2",  // 2 for RTCP
2833             *remote_inbound_rtp.transport_id);
2834   EXPECT_TRUE(report->Get(*remote_inbound_rtp.transport_id));
2835 }
2836 
2837 INSTANTIATE_TEST_SUITE_P(All,
2838                          RTCStatsCollectorTestWithParamKind,
2839                          ::testing::Values(cricket::MEDIA_TYPE_AUDIO,    // "/0"
2840                                            cricket::MEDIA_TYPE_VIDEO));  // "/1"
2841 
TEST_F(RTCStatsCollectorTest,RTCVideoSourceStatsNotCollectedForSenderWithoutTrack)2842 TEST_F(RTCStatsCollectorTest,
2843        RTCVideoSourceStatsNotCollectedForSenderWithoutTrack) {
2844   const uint32_t kSsrc = 4;
2845   const int kAttachmentId = 42;
2846 
2847   cricket::VideoMediaInfo video_media_info;
2848   video_media_info.senders.push_back(cricket::VideoSenderInfo());
2849   video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2850   video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2851   video_media_info.senders[0].framerate_input = 29;
2852   auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2853   video_media_channel->SetStats(video_media_info);
2854 
2855   rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2856       cricket::MEDIA_TYPE_VIDEO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
2857   pc_->AddSender(sender);
2858 
2859   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2860   EXPECT_FALSE(report->Get("RTCVideoSource_42"));
2861 }
2862 
TEST_F(RTCStatsCollectorTest,GetStatsWithSenderSelector)2863 TEST_F(RTCStatsCollectorTest, GetStatsWithSenderSelector) {
2864   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2865   // Expected stats graph when filtered by sender:
2866   //
2867   //  +--- track (sender)
2868   //  |             ^
2869   //  |             |
2870   //  | +--------- outbound-rtp
2871   //  | |           |        |
2872   //  | |           v        v
2873   //  | |  codec (send)     transport
2874   //  v v
2875   //  media-source
2876   rtc::scoped_refptr<const RTCStatsReport> sender_report =
2877       stats_->GetStatsReportWithSenderSelector(graph.sender);
2878   EXPECT_TRUE(sender_report);
2879   EXPECT_EQ(sender_report->timestamp_us(), graph.full_report->timestamp_us());
2880   EXPECT_EQ(sender_report->size(), 5u);
2881   EXPECT_TRUE(sender_report->Get(graph.send_codec_id));
2882   EXPECT_FALSE(sender_report->Get(graph.recv_codec_id));
2883   EXPECT_TRUE(sender_report->Get(graph.outbound_rtp_id));
2884   EXPECT_FALSE(sender_report->Get(graph.inbound_rtp_id));
2885   EXPECT_TRUE(sender_report->Get(graph.transport_id));
2886   EXPECT_TRUE(sender_report->Get(graph.sender_track_id));
2887   EXPECT_FALSE(sender_report->Get(graph.receiver_track_id));
2888   EXPECT_FALSE(sender_report->Get(graph.remote_stream_id));
2889   EXPECT_FALSE(sender_report->Get(graph.peer_connection_id));
2890   EXPECT_TRUE(sender_report->Get(graph.media_source_id));
2891 }
2892 
TEST_F(RTCStatsCollectorTest,GetStatsWithReceiverSelector)2893 TEST_F(RTCStatsCollectorTest, GetStatsWithReceiverSelector) {
2894   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2895   // Expected stats graph when filtered by receiver:
2896   //
2897   //                                                       track (receiver)
2898   //                                                         ^
2899   //                                                         |
2900   //                              inbound-rtp ---------------+
2901   //                               |       |
2902   //                               v       v
2903   //                        transport     codec (recv)
2904   rtc::scoped_refptr<const RTCStatsReport> receiver_report =
2905       stats_->GetStatsReportWithReceiverSelector(graph.receiver);
2906   EXPECT_TRUE(receiver_report);
2907   EXPECT_EQ(receiver_report->size(), 4u);
2908   EXPECT_EQ(receiver_report->timestamp_us(), graph.full_report->timestamp_us());
2909   EXPECT_FALSE(receiver_report->Get(graph.send_codec_id));
2910   EXPECT_TRUE(receiver_report->Get(graph.recv_codec_id));
2911   EXPECT_FALSE(receiver_report->Get(graph.outbound_rtp_id));
2912   EXPECT_TRUE(receiver_report->Get(graph.inbound_rtp_id));
2913   EXPECT_TRUE(receiver_report->Get(graph.transport_id));
2914   EXPECT_FALSE(receiver_report->Get(graph.sender_track_id));
2915   EXPECT_TRUE(receiver_report->Get(graph.receiver_track_id));
2916   EXPECT_FALSE(receiver_report->Get(graph.remote_stream_id));
2917   EXPECT_FALSE(receiver_report->Get(graph.peer_connection_id));
2918   EXPECT_FALSE(receiver_report->Get(graph.media_source_id));
2919 }
2920 
TEST_F(RTCStatsCollectorTest,GetStatsWithNullSenderSelector)2921 TEST_F(RTCStatsCollectorTest, GetStatsWithNullSenderSelector) {
2922   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2923   rtc::scoped_refptr<const RTCStatsReport> empty_report =
2924       stats_->GetStatsReportWithSenderSelector(nullptr);
2925   EXPECT_TRUE(empty_report);
2926   EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2927   EXPECT_EQ(empty_report->size(), 0u);
2928 }
2929 
TEST_F(RTCStatsCollectorTest,GetStatsWithNullReceiverSelector)2930 TEST_F(RTCStatsCollectorTest, GetStatsWithNullReceiverSelector) {
2931   ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2932   rtc::scoped_refptr<const RTCStatsReport> empty_report =
2933       stats_->GetStatsReportWithReceiverSelector(nullptr);
2934   EXPECT_TRUE(empty_report);
2935   EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2936   EXPECT_EQ(empty_report->size(), 0u);
2937 }
2938 
2939 // When the PC has not had SetLocalDescription done, tracks all have
2940 // SSRC 0, meaning "unconnected".
2941 // In this state, we report on track stats, but not RTP stats.
TEST_F(RTCStatsCollectorTest,StatsReportedOnZeroSsrc)2942 TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
2943   rtc::scoped_refptr<MediaStreamTrackInterface> track =
2944       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2945                       MediaStreamTrackInterface::kLive);
2946   rtc::scoped_refptr<MockRtpSenderInternal> sender =
2947       CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 0, 49, {});
2948   pc_->AddSender(sender);
2949 
2950   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2951 
2952   std::vector<const RTCMediaStreamTrackStats*> track_stats =
2953       report->GetStatsOfType<RTCMediaStreamTrackStats>();
2954   EXPECT_EQ(1U, track_stats.size());
2955 
2956   std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
2957       report->GetStatsOfType<RTCRTPStreamStats>();
2958   EXPECT_EQ(0U, rtp_stream_stats.size());
2959 }
2960 
TEST_F(RTCStatsCollectorTest,DoNotCrashOnSsrcChange)2961 TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
2962   rtc::scoped_refptr<MediaStreamTrackInterface> track =
2963       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2964                       MediaStreamTrackInterface::kLive);
2965   rtc::scoped_refptr<MockRtpSenderInternal> sender =
2966       CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 4711, 49, {});
2967   pc_->AddSender(sender);
2968 
2969   // We do not generate any matching voice_sender_info stats.
2970   rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2971 
2972   std::vector<const RTCMediaStreamTrackStats*> track_stats =
2973       report->GetStatsOfType<RTCMediaStreamTrackStats>();
2974   EXPECT_EQ(1U, track_stats.size());
2975 }
2976 
2977 // Used for test below, to test calling GetStatsReport during a callback.
2978 class RecursiveCallback : public RTCStatsCollectorCallback {
2979  public:
RecursiveCallback(RTCStatsCollectorWrapper * stats)2980   explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
2981 
OnStatsDelivered(const rtc::scoped_refptr<const RTCStatsReport> & report)2982   void OnStatsDelivered(
2983       const rtc::scoped_refptr<const RTCStatsReport>& report) override {
2984     stats_->GetStatsReport();
2985     called_ = true;
2986   }
2987 
called() const2988   bool called() const { return called_; }
2989 
2990  private:
2991   RTCStatsCollectorWrapper* stats_;
2992   bool called_ = false;
2993 };
2994 
2995 // Test that nothing bad happens if a callback causes GetStatsReport to be
2996 // called again recursively. Regression test for crbug.com/webrtc/8973.
TEST_F(RTCStatsCollectorTest,DoNotCrashWhenGetStatsCalledDuringCallback)2997 TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
2998   rtc::scoped_refptr<RecursiveCallback> callback1(
2999       new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
3000   rtc::scoped_refptr<RecursiveCallback> callback2(
3001       new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
3002   stats_->stats_collector()->GetStatsReport(callback1);
3003   stats_->stats_collector()->GetStatsReport(callback2);
3004   EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
3005   EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
3006 }
3007 
3008 class RTCTestStats : public RTCStats {
3009  public:
3010   WEBRTC_RTCSTATS_DECL();
3011 
RTCTestStats(const std::string & id,int64_t timestamp_us)3012   RTCTestStats(const std::string& id, int64_t timestamp_us)
3013       : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
3014 
3015   RTCStatsMember<int32_t> dummy_stat;
3016 };
3017 
3018 WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat)
3019 
3020 // Overrides the stats collection to verify thread usage and that the resulting
3021 // partial reports are merged.
3022 class FakeRTCStatsCollector : public RTCStatsCollector,
3023                               public RTCStatsCollectorCallback {
3024  public:
Create(PeerConnectionInternal * pc,int64_t cache_lifetime_us)3025   static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
3026       PeerConnectionInternal* pc,
3027       int64_t cache_lifetime_us) {
3028     return rtc::scoped_refptr<FakeRTCStatsCollector>(
3029         new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
3030                                                          cache_lifetime_us));
3031   }
3032 
3033   // RTCStatsCollectorCallback implementation.
OnStatsDelivered(const rtc::scoped_refptr<const RTCStatsReport> & report)3034   void OnStatsDelivered(
3035       const rtc::scoped_refptr<const RTCStatsReport>& report) override {
3036     EXPECT_TRUE(signaling_thread_->IsCurrent());
3037     MutexLock lock(&lock_);
3038     delivered_report_ = report;
3039   }
3040 
VerifyThreadUsageAndResultsMerging()3041   void VerifyThreadUsageAndResultsMerging() {
3042     GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
3043     EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
3044   }
3045 
HasVerifiedResults()3046   bool HasVerifiedResults() {
3047     EXPECT_TRUE(signaling_thread_->IsCurrent());
3048     MutexLock lock(&lock_);
3049     if (!delivered_report_)
3050       return false;
3051     EXPECT_EQ(produced_on_signaling_thread_, 1);
3052     EXPECT_EQ(produced_on_network_thread_, 1);
3053 
3054     EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
3055     EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
3056 
3057     produced_on_signaling_thread_ = 0;
3058     produced_on_network_thread_ = 0;
3059     delivered_report_ = nullptr;
3060     return true;
3061   }
3062 
3063  protected:
FakeRTCStatsCollector(PeerConnectionInternal * pc,int64_t cache_lifetime)3064   FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
3065       : RTCStatsCollector(pc, cache_lifetime),
3066         signaling_thread_(pc->signaling_thread()),
3067         worker_thread_(pc->worker_thread()),
3068         network_thread_(pc->network_thread()) {}
3069 
ProducePartialResultsOnSignalingThreadImpl(int64_t timestamp_us,RTCStatsReport * partial_report)3070   void ProducePartialResultsOnSignalingThreadImpl(
3071       int64_t timestamp_us,
3072       RTCStatsReport* partial_report) override {
3073     EXPECT_TRUE(signaling_thread_->IsCurrent());
3074     {
3075       MutexLock lock(&lock_);
3076       EXPECT_FALSE(delivered_report_);
3077       ++produced_on_signaling_thread_;
3078     }
3079 
3080     partial_report->AddStats(std::unique_ptr<const RTCStats>(
3081         new RTCTestStats("SignalingThreadStats", timestamp_us)));
3082   }
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)3083   void ProducePartialResultsOnNetworkThreadImpl(
3084       int64_t timestamp_us,
3085       const std::map<std::string, cricket::TransportStats>&
3086           transport_stats_by_name,
3087       const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
3088       RTCStatsReport* partial_report) override {
3089     EXPECT_TRUE(network_thread_->IsCurrent());
3090     {
3091       MutexLock lock(&lock_);
3092       EXPECT_FALSE(delivered_report_);
3093       ++produced_on_network_thread_;
3094     }
3095 
3096     partial_report->AddStats(std::unique_ptr<const RTCStats>(
3097         new RTCTestStats("NetworkThreadStats", timestamp_us)));
3098   }
3099 
3100  private:
3101   rtc::Thread* const signaling_thread_;
3102   rtc::Thread* const worker_thread_;
3103   rtc::Thread* const network_thread_;
3104 
3105   Mutex lock_;
3106   rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
3107   int produced_on_signaling_thread_ = 0;
3108   int produced_on_network_thread_ = 0;
3109 };
3110 
TEST(RTCStatsCollectorTestWithFakeCollector,ThreadUsageAndResultsMerging)3111 TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
3112   rtc::scoped_refptr<FakePeerConnectionForStats> pc(
3113       new rtc::RefCountedObject<FakePeerConnectionForStats>());
3114   rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
3115       FakeRTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec));
3116   stats_collector->VerifyThreadUsageAndResultsMerging();
3117 }
3118 
3119 }  // namespace
3120 
3121 }  // namespace webrtc
3122