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