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