blob: 08fa41537a9263707c6eaf2b3713ea62b3f94592 [file] [log] [blame]
hbosd565b732016-08-30 14:04:35 -07001/*
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
hbos9e302742017-01-20 02:47:10 -080011#include <initializer_list>
hbosd565b732016-08-30 14:04:35 -070012#include <memory>
hbosda389e32016-10-25 10:55:08 -070013#include <ostream>
hbosd565b732016-08-30 14:04:35 -070014#include <string>
Steve Anton36b29d12017-10-30 09:57:42 -070015#include <utility>
hbosd565b732016-08-30 14:04:35 -070016#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "api/rtpparameters.h"
19#include "api/stats/rtcstats_objects.h"
20#include "api/stats/rtcstatsreport.h"
Sebastian Jansson5f83cf02018-05-08 14:52:22 +020021#include "api/units/time_delta.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "p2p/base/p2pconstants.h"
23#include "p2p/base/port.h"
24#include "pc/mediastream.h"
25#include "pc/mediastreamtrack.h"
Steve Anton5b387312018-02-02 16:00:20 -080026#include "pc/rtcstatscollector.h"
27#include "pc/test/fakepeerconnectionforstats.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "pc/test/mock_datachannel.h"
Steve Anton57858b32018-02-15 15:19:50 -080029#include "pc/test/mock_rtpreceiverinternal.h"
30#include "pc/test/mock_rtpsenderinternal.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "pc/test/rtcstatsobtainer.h"
32#include "rtc_base/checks.h"
33#include "rtc_base/fakeclock.h"
34#include "rtc_base/fakesslidentity.h"
35#include "rtc_base/gunit.h"
36#include "rtc_base/logging.h"
Steve Anton5b387312018-02-02 16:00:20 -080037#include "rtc_base/ptr_util.h"
38#include "rtc_base/stringutils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020039#include "rtc_base/timeutils.h"
hbosd565b732016-08-30 14:04:35 -070040
Steve Anton57858b32018-02-15 15:19:50 -080041using testing::AtLeast;
hbos6ab97ce2016-10-03 14:16:56 -070042using testing::Invoke;
hbosd565b732016-08-30 14:04:35 -070043using testing::Return;
hbosd565b732016-08-30 14:04:35 -070044
45namespace webrtc {
46
hbosda389e32016-10-25 10:55:08 -070047// These are used by gtest code, such as if |EXPECT_EQ| fails.
48void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070049 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070050}
51
hbos0adb8282016-11-23 02:32:06 -080052void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070053 *os << stats.ToJson();
hbos0adb8282016-11-23 02:32:06 -080054}
55
hbosda389e32016-10-25 10:55:08 -070056void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070057 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070058}
59
60void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070061 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070062}
63
64void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070065 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070066}
67
68void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070069 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070070}
71
72void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070073 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070074}
75
hbos09bc1282016-11-08 06:29:22 -080076void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070077 *os << stats.ToJson();
hbos09bc1282016-11-08 06:29:22 -080078}
79
80void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070081 *os << stats.ToJson();
hbos09bc1282016-11-08 06:29:22 -080082}
83
hboseeafe942016-11-01 03:00:17 -070084void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070085 *os << stats.ToJson();
hboseeafe942016-11-01 03:00:17 -070086}
87
hbos6ded1902016-11-01 01:50:46 -070088void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070089 *os << stats.ToJson();
hbos6ded1902016-11-01 01:50:46 -070090}
91
hbosda389e32016-10-25 10:55:08 -070092void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -070093 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -070094}
95
hbosc82f2e12016-09-05 01:36:50 -070096namespace {
97
98const int64_t kGetStatsReportTimeoutMs = 1000;
99
hbos6ab97ce2016-10-03 14:16:56 -0700100struct CertificateInfo {
101 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
102 std::vector<std::string> ders;
103 std::vector<std::string> pems;
104 std::vector<std::string> fingerprints;
105};
106
Harald Alvestranda3dab842018-01-14 09:18:58 +0100107// Return the ID for an object of the given type in a report.
108// The object must be present and be unique.
109template <typename T>
110std::string IdForType(const RTCStatsReport* report) {
111 auto stats_of_my_type = report->RTCStatsReport::GetStatsOfType<T>();
112 // We cannot use ASSERT here, since we're within a function.
113 EXPECT_EQ(1, stats_of_my_type.size())
114 << "Unexpected number of stats of this type";
115 if (stats_of_my_type.size() == 1) {
116 return stats_of_my_type[0]->id();
117 } else {
118 // Return something that is not going to be a valid stas ID.
119 return "Type not found";
120 }
121}
122
hbos6ab97ce2016-10-03 14:16:56 -0700123std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
124 const std::vector<std::string>& ders) {
125 RTC_CHECK(!ders.empty());
126 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
127 info->ders = ders;
128 for (const std::string& der : ders) {
129 info->pems.push_back(rtc::SSLIdentity::DerToPem(
130 "CERTIFICATE",
131 reinterpret_cast<const unsigned char*>(der.c_str()),
132 der.length()));
133 }
134 info->certificate =
135 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800136 new rtc::FakeSSLIdentity(info->pems)));
hbos6ab97ce2016-10-03 14:16:56 -0700137 // Strip header/footer and newline characters of PEM strings.
138 for (size_t i = 0; i < info->pems.size(); ++i) {
139 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
140 "", 0, &info->pems[i]);
141 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
142 "", 0, &info->pems[i]);
143 rtc::replace_substrs("\n", 1,
144 "", 0, &info->pems[i]);
145 }
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800146 // Fingerprints for the whole certificate chain, starting with leaf
147 // certificate.
148 const rtc::SSLCertChain& chain = info->certificate->ssl_cert_chain();
149 std::unique_ptr<rtc::SSLFingerprint> fp;
150 for (size_t i = 0; i < chain.GetSize(); i++) {
151 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain.Get(i)));
152 EXPECT_TRUE(fp);
153 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
hbos6ab97ce2016-10-03 14:16:56 -0700154 }
155 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
156 return info;
157}
158
hbosab9f6e42016-10-07 02:18:47 -0700159std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
160 const std::string& hostname,
161 int port,
162 const std::string& protocol,
Gary Liu37e489c2017-11-21 10:49:36 -0800163 const rtc::AdapterType adapter_type,
hbosab9f6e42016-10-07 02:18:47 -0700164 const std::string& candidate_type,
165 uint32_t priority) {
166 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
167 candidate->set_address(rtc::SocketAddress(hostname, port));
168 candidate->set_protocol(protocol);
Gary Liu37e489c2017-11-21 10:49:36 -0800169 candidate->set_network_type(adapter_type);
hbosab9f6e42016-10-07 02:18:47 -0700170 candidate->set_type(candidate_type);
171 candidate->set_priority(priority);
172 return candidate;
173}
174
hbos09bc1282016-11-08 06:29:22 -0800175class FakeAudioTrackForStats
176 : public MediaStreamTrack<AudioTrackInterface> {
177 public:
178 static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
179 const std::string& id,
hbos9e302742017-01-20 02:47:10 -0800180 MediaStreamTrackInterface::TrackState state) {
hbos09bc1282016-11-08 06:29:22 -0800181 rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
hbos9e302742017-01-20 02:47:10 -0800182 new rtc::RefCountedObject<FakeAudioTrackForStats>(id));
hbos09bc1282016-11-08 06:29:22 -0800183 audio_track_stats->set_state(state);
184 return audio_track_stats;
185 }
186
Steve Anton36b29d12017-10-30 09:57:42 -0700187 explicit FakeAudioTrackForStats(const std::string& id)
188 : MediaStreamTrack<AudioTrackInterface>(id) {}
hbos09bc1282016-11-08 06:29:22 -0800189
190 std::string kind() const override {
191 return MediaStreamTrackInterface::kAudioKind;
192 }
193 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
194 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
195 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
hbos9e302742017-01-20 02:47:10 -0800196 bool GetSignalLevel(int* level) override { return false; }
hbos09bc1282016-11-08 06:29:22 -0800197 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
hbos9e302742017-01-20 02:47:10 -0800198 return nullptr;
hbos09bc1282016-11-08 06:29:22 -0800199 }
hbos09bc1282016-11-08 06:29:22 -0800200};
201
202class FakeVideoTrackForStats
203 : public MediaStreamTrack<VideoTrackInterface> {
204 public:
205 static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
206 const std::string& id,
hbos9e302742017-01-20 02:47:10 -0800207 MediaStreamTrackInterface::TrackState state) {
hbos09bc1282016-11-08 06:29:22 -0800208 rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
hbos9e302742017-01-20 02:47:10 -0800209 new rtc::RefCountedObject<FakeVideoTrackForStats>(id));
hbos09bc1282016-11-08 06:29:22 -0800210 video_track->set_state(state);
211 return video_track;
212 }
213
Steve Anton36b29d12017-10-30 09:57:42 -0700214 explicit FakeVideoTrackForStats(const std::string& id)
215 : MediaStreamTrack<VideoTrackInterface>(id) {}
hbos09bc1282016-11-08 06:29:22 -0800216
217 std::string kind() const override {
218 return MediaStreamTrackInterface::kVideoKind;
219 }
perkj773be362017-07-31 23:22:01 -0700220
221 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
222 const rtc::VideoSinkWants& wants) override{};
223 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override{};
224
hbos9e302742017-01-20 02:47:10 -0800225 VideoTrackSourceInterface* GetSource() const override { return nullptr; }
hbos09bc1282016-11-08 06:29:22 -0800226};
227
hbos84abeb12017-01-16 06:16:44 -0800228rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
229 cricket::MediaType media_type,
hbos9e302742017-01-20 02:47:10 -0800230 const std::string& track_id,
231 MediaStreamTrackInterface::TrackState track_state) {
hbos84abeb12017-01-16 06:16:44 -0800232 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800233 return FakeAudioTrackForStats::Create(track_id, track_state);
hbos84abeb12017-01-16 06:16:44 -0800234 } else {
235 RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
hbos9e302742017-01-20 02:47:10 -0800236 return FakeVideoTrackForStats::Create(track_id, track_state);
hbos84abeb12017-01-16 06:16:44 -0800237 }
238}
239
Steve Anton57858b32018-02-15 15:19:50 -0800240rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
Mirko Bonadeic61ce0d2017-11-21 17:04:20 +0100241 const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100242 uint32_t ssrc,
Harald Alvestranda3dab842018-01-14 09:18:58 +0100243 int attachment_id,
244 std::vector<std::string> local_stream_ids) {
Steve Anton57858b32018-02-15 15:19:50 -0800245 rtc::scoped_refptr<MockRtpSenderInternal> sender(
246 new rtc::RefCountedObject<MockRtpSenderInternal>());
hbos9e302742017-01-20 02:47:10 -0800247 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
248 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
249 EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(
250 track->kind() == MediaStreamTrackInterface::kAudioKind
251 ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO));
252 EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke(
253 [ssrc]() {
254 RtpParameters params;
255 params.encodings.push_back(RtpEncodingParameters());
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100256 params.encodings[0].ssrc = ssrc;
hbos9e302742017-01-20 02:47:10 -0800257 return params;
258 }));
Harald Alvestrandc72af932018-01-11 17:18:19 +0100259 EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
Harald Alvestranda3dab842018-01-14 09:18:58 +0100260 EXPECT_CALL(*sender, stream_ids()).WillRepeatedly(Return(local_stream_ids));
hbos9e302742017-01-20 02:47:10 -0800261 return sender;
262}
263
Steve Anton57858b32018-02-15 15:19:50 -0800264rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
Mirko Bonadeic61ce0d2017-11-21 17:04:20 +0100265 const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100266 uint32_t ssrc,
267 int attachment_id) {
Steve Anton57858b32018-02-15 15:19:50 -0800268 rtc::scoped_refptr<MockRtpReceiverInternal> receiver(
269 new rtc::RefCountedObject<MockRtpReceiverInternal>());
hbos9e302742017-01-20 02:47:10 -0800270 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
Harald Alvestranda3dab842018-01-14 09:18:58 +0100271 EXPECT_CALL(*receiver, streams())
272 .WillRepeatedly(
273 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>({})));
274
hbos9e302742017-01-20 02:47:10 -0800275 EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return(
276 track->kind() == MediaStreamTrackInterface::kAudioKind
277 ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO));
278 EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke(
279 [ssrc]() {
280 RtpParameters params;
281 params.encodings.push_back(RtpEncodingParameters());
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100282 params.encodings[0].ssrc = ssrc;
hbos9e302742017-01-20 02:47:10 -0800283 return params;
284 }));
Harald Alvestrandc72af932018-01-11 17:18:19 +0100285 EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
hbos9e302742017-01-20 02:47:10 -0800286 return receiver;
287}
288
Steve Anton5b387312018-02-02 16:00:20 -0800289class RTCStatsCollectorWrapper {
hbosd565b732016-08-30 14:04:35 -0700290 public:
Steve Anton5b387312018-02-02 16:00:20 -0800291 explicit RTCStatsCollectorWrapper(
292 rtc::scoped_refptr<FakePeerConnectionForStats> pc)
293 : pc_(pc),
294 stats_collector_(
295 RTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec)) {
hbosd565b732016-08-30 14:04:35 -0700296 }
297
Steve Anton5b387312018-02-02 16:00:20 -0800298 rtc::scoped_refptr<RTCStatsCollector> stats_collector() {
299 return stats_collector_;
hbosd565b732016-08-30 14:04:35 -0700300 }
301
Henrik Boström5b3541f2018-03-19 13:52:56 +0100302 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
303 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
304 stats_collector_->GetStatsReport(callback);
305 return WaitForReport(callback);
306 }
307
308 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithSenderSelector(
309 rtc::scoped_refptr<RtpSenderInternal> selector) {
310 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
311 stats_collector_->GetStatsReport(selector, callback);
312 return WaitForReport(callback);
313 }
314
315 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithReceiverSelector(
316 rtc::scoped_refptr<RtpReceiverInternal> selector) {
317 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
318 stats_collector_->GetStatsReport(selector, callback);
319 return WaitForReport(callback);
320 }
321
Steve Anton5b387312018-02-02 16:00:20 -0800322 rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
323 stats_collector_->ClearCachedStatsReport();
324 return GetStatsReport();
325 }
326
Henrik Boström5b3541f2018-03-19 13:52:56 +0100327 rtc::scoped_refptr<MockRtpSenderInternal> SetupLocalTrackAndSender(
328 cricket::MediaType media_type,
329 const std::string& track_id,
330 uint32_t ssrc,
331 bool add_stream) {
Harald Alvestrand89061872018-01-02 14:08:34 +0100332 rtc::scoped_refptr<MediaStream> local_stream;
333 if (add_stream) {
Seth Hampson845e8782018-03-02 11:34:10 -0800334 local_stream = MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -0800335 pc_->mutable_local_streams()->AddStream(local_stream);
Harald Alvestrand89061872018-01-02 14:08:34 +0100336 }
hbos84abeb12017-01-16 06:16:44 -0800337
338 rtc::scoped_refptr<MediaStreamTrackInterface> track;
339 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800340 track = CreateFakeTrack(media_type, track_id,
341 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100342 if (add_stream) {
343 local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
344 }
hbos84abeb12017-01-16 06:16:44 -0800345 } else {
hbos9e302742017-01-20 02:47:10 -0800346 track = CreateFakeTrack(media_type, track_id,
347 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100348 if (add_stream) {
349 local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
350 }
hbos84abeb12017-01-16 06:16:44 -0800351 }
352
Steve Anton57858b32018-02-15 15:19:50 -0800353 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Harald Alvestranda3dab842018-01-14 09:18:58 +0100354 CreateMockSender(track, ssrc, 50, {});
Steve Anton5b387312018-02-02 16:00:20 -0800355 pc_->AddSender(sender);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100356 return sender;
hbos84abeb12017-01-16 06:16:44 -0800357 }
358
Henrik Boström5b3541f2018-03-19 13:52:56 +0100359 rtc::scoped_refptr<MockRtpReceiverInternal> SetupRemoteTrackAndReceiver(
360 cricket::MediaType media_type,
361 const std::string& track_id,
362 const std::string& stream_id,
363 uint32_t ssrc) {
hbos84abeb12017-01-16 06:16:44 -0800364 rtc::scoped_refptr<MediaStream> remote_stream =
Henrik Boström5b3541f2018-03-19 13:52:56 +0100365 MediaStream::Create(stream_id);
Steve Anton5b387312018-02-02 16:00:20 -0800366 pc_->mutable_remote_streams()->AddStream(remote_stream);
hbos84abeb12017-01-16 06:16:44 -0800367
368 rtc::scoped_refptr<MediaStreamTrackInterface> track;
369 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800370 track = CreateFakeTrack(media_type, track_id,
371 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800372 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
373 } else {
hbos9e302742017-01-20 02:47:10 -0800374 track = CreateFakeTrack(media_type, track_id,
375 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800376 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
377 }
378
Steve Anton57858b32018-02-15 15:19:50 -0800379 rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
Harald Alvestrandc72af932018-01-11 17:18:19 +0100380 CreateMockReceiver(track, ssrc, 62);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100381 EXPECT_CALL(*receiver, streams())
382 .WillRepeatedly(
383 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
384 {remote_stream})));
Steve Anton5b387312018-02-02 16:00:20 -0800385 pc_->AddReceiver(receiver);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100386 return receiver;
hbos84abeb12017-01-16 06:16:44 -0800387 }
388
hbos9e302742017-01-20 02:47:10 -0800389 // Attaches tracks to peer connections by configuring RTP senders and RTP
390 // receivers according to the tracks' pairings with
391 // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
392 // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
393 // be associated with one |[Voice/Video]ReceiverInfo|.
394 void CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +0100395 std::initializer_list<
396 std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
397 local_audio_track_info_pairs,
398 std::initializer_list<
399 std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
400 remote_audio_track_info_pairs,
401 std::initializer_list<
402 std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
403 local_video_track_info_pairs,
404 std::initializer_list<
405 std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
406 remote_video_track_info_pairs,
407 std::vector<std::string> local_stream_ids,
408 std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
Steve Anton5b387312018-02-02 16:00:20 -0800409 cricket::VoiceMediaInfo voice_media_info;
410 cricket::VideoMediaInfo video_media_info;
411
hbos9e302742017-01-20 02:47:10 -0800412 // Local audio tracks and voice sender infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100413 int attachment_id = 147;
hbos9e302742017-01-20 02:47:10 -0800414 for (auto& pair : local_audio_track_info_pairs) {
415 MediaStreamTrackInterface* local_audio_track = pair.first;
416 const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
417 RTC_DCHECK_EQ(local_audio_track->kind(),
418 MediaStreamTrackInterface::kAudioKind);
419
Steve Anton5b387312018-02-02 16:00:20 -0800420 voice_media_info.senders.push_back(voice_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800421 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Harald Alvestrandc72af932018-01-11 17:18:19 +0100422 rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
Harald Alvestranda3dab842018-01-14 09:18:58 +0100423 voice_sender_info.local_stats[0].ssrc, attachment_id++,
424 local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800425 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800426 }
Steve Anton5b387312018-02-02 16:00:20 -0800427
hbos9e302742017-01-20 02:47:10 -0800428 // Remote audio tracks and voice receiver infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100429 attachment_id = 181;
hbos9e302742017-01-20 02:47:10 -0800430 for (auto& pair : remote_audio_track_info_pairs) {
431 MediaStreamTrackInterface* remote_audio_track = pair.first;
432 const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
433 RTC_DCHECK_EQ(remote_audio_track->kind(),
434 MediaStreamTrackInterface::kAudioKind);
435
Steve Anton5b387312018-02-02 16:00:20 -0800436 voice_media_info.receivers.push_back(voice_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800437 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
438 CreateMockReceiver(
439 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
440 voice_receiver_info.local_stats[0].ssrc, attachment_id++);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100441 EXPECT_CALL(*rtp_receiver, streams())
442 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800443 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800444 }
Steve Anton5b387312018-02-02 16:00:20 -0800445
hbos9e302742017-01-20 02:47:10 -0800446 // Local video tracks and video sender infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100447 attachment_id = 151;
hbos9e302742017-01-20 02:47:10 -0800448 for (auto& pair : local_video_track_info_pairs) {
449 MediaStreamTrackInterface* local_video_track = pair.first;
450 const cricket::VideoSenderInfo& video_sender_info = pair.second;
451 RTC_DCHECK_EQ(local_video_track->kind(),
452 MediaStreamTrackInterface::kVideoKind);
453
Steve Anton5b387312018-02-02 16:00:20 -0800454 video_media_info.senders.push_back(video_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800455 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Harald Alvestrandc72af932018-01-11 17:18:19 +0100456 rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
Harald Alvestranda3dab842018-01-14 09:18:58 +0100457 video_sender_info.local_stats[0].ssrc, attachment_id++,
458 local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800459 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800460 }
Steve Anton5b387312018-02-02 16:00:20 -0800461
hbos9e302742017-01-20 02:47:10 -0800462 // Remote video tracks and video receiver infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100463 attachment_id = 191;
hbos9e302742017-01-20 02:47:10 -0800464 for (auto& pair : remote_video_track_info_pairs) {
465 MediaStreamTrackInterface* remote_video_track = pair.first;
466 const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
467 RTC_DCHECK_EQ(remote_video_track->kind(),
468 MediaStreamTrackInterface::kVideoKind);
469
Steve Anton5b387312018-02-02 16:00:20 -0800470 video_media_info.receivers.push_back(video_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800471 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
472 CreateMockReceiver(
473 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
474 video_receiver_info.local_stats[0].ssrc, attachment_id++);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100475 EXPECT_CALL(*rtp_receiver, streams())
476 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800477 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800478 }
hbos9e302742017-01-20 02:47:10 -0800479
Steve Anton5b387312018-02-02 16:00:20 -0800480 auto* voice_media_channel = pc_->AddVoiceChannel("audio", "transport");
481 voice_media_channel->SetStats(voice_media_info);
hbos9e302742017-01-20 02:47:10 -0800482
Steve Anton5b387312018-02-02 16:00:20 -0800483 auto* video_media_channel = pc_->AddVideoChannel("video", "transport");
484 video_media_channel->SetStats(video_media_info);
hbos9e302742017-01-20 02:47:10 -0800485 }
486
hbosd565b732016-08-30 14:04:35 -0700487 private:
Henrik Boström5b3541f2018-03-19 13:52:56 +0100488 rtc::scoped_refptr<const RTCStatsReport> WaitForReport(
489 rtc::scoped_refptr<RTCStatsObtainer> callback) {
490 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
491 int64_t after = rtc::TimeUTCMicros();
492 for (const RTCStats& stats : *callback->report()) {
493 EXPECT_LE(stats.timestamp_us(), after);
494 }
495 return callback->report();
496 }
497
Steve Anton5b387312018-02-02 16:00:20 -0800498 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
499 rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
hbosd565b732016-08-30 14:04:35 -0700500};
501
hbosc82f2e12016-09-05 01:36:50 -0700502class RTCStatsCollectorTest : public testing::Test {
503 public:
504 RTCStatsCollectorTest()
Steve Anton5b387312018-02-02 16:00:20 -0800505 : pc_(new rtc::RefCountedObject<FakePeerConnectionForStats>()),
506 stats_(new RTCStatsCollectorWrapper(pc_)) {}
hbosc82f2e12016-09-05 01:36:50 -0700507
hbos6ab97ce2016-10-03 14:16:56 -0700508 void ExpectReportContainsCertificateInfo(
509 const rtc::scoped_refptr<const RTCStatsReport>& report,
hbos23368e12016-12-21 04:29:17 -0800510 const CertificateInfo& certinfo) {
511 for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
512 RTCCertificateStats expected_certificate_stats(
513 "RTCCertificate_" + certinfo.fingerprints[i],
514 report->timestamp_us());
515 expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
516 expected_certificate_stats.fingerprint_algorithm = "sha-1";
517 expected_certificate_stats.base64_certificate = certinfo.pems[i];
518 if (i + 1 < certinfo.fingerprints.size()) {
519 expected_certificate_stats.issuer_certificate_id =
520 "RTCCertificate_" + certinfo.fingerprints[i + 1];
hbos6ab97ce2016-10-03 14:16:56 -0700521 }
hbos23368e12016-12-21 04:29:17 -0800522 ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
523 EXPECT_EQ(expected_certificate_stats,
524 report->Get(expected_certificate_stats.id())->cast_to<
525 RTCCertificateStats>());
hbos6ab97ce2016-10-03 14:16:56 -0700526 }
527 }
528
Henrik Boström5b3541f2018-03-19 13:52:56 +0100529 struct ExampleStatsGraph {
530 rtc::scoped_refptr<RtpSenderInternal> sender;
531 rtc::scoped_refptr<RtpReceiverInternal> receiver;
532
533 rtc::scoped_refptr<const RTCStatsReport> full_report;
534 std::string send_codec_id;
535 std::string recv_codec_id;
536 std::string outbound_rtp_id;
537 std::string inbound_rtp_id;
538 std::string transport_id;
539 std::string sender_track_id;
540 std::string receiver_track_id;
541 std::string remote_stream_id;
542 std::string peer_connection_id;
543 };
544
545 // Sets up the example stats graph (see ASCII art below) used for testing the
546 // stats selection algorithm,
547 // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm.
548 // These tests test the integration of the stats traversal algorithm inside of
549 // RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
550 // traversal tests.
551 ExampleStatsGraph SetupExampleStatsGraphForSelectorTests() {
552 ExampleStatsGraph graph;
553
554 // codec (send)
555 graph.send_codec_id = "RTCCodec_VideoMid_Outbound_1";
556 cricket::VideoMediaInfo video_media_info;
557 RtpCodecParameters send_codec;
558 send_codec.payload_type = 1;
559 send_codec.clock_rate = 0;
560 video_media_info.send_codecs.insert(
561 std::make_pair(send_codec.payload_type, send_codec));
562 // codec (recv)
563 graph.recv_codec_id = "RTCCodec_VideoMid_Inbound_2";
564 RtpCodecParameters recv_codec;
565 recv_codec.payload_type = 2;
566 recv_codec.clock_rate = 0;
567 video_media_info.receive_codecs.insert(
568 std::make_pair(recv_codec.payload_type, recv_codec));
569 // outbound-rtp
570 graph.outbound_rtp_id = "RTCOutboundRTPVideoStream_3";
571 video_media_info.senders.push_back(cricket::VideoSenderInfo());
572 video_media_info.senders[0].local_stats.push_back(
573 cricket::SsrcSenderInfo());
574 video_media_info.senders[0].local_stats[0].ssrc = 3;
575 video_media_info.senders[0].codec_payload_type = send_codec.payload_type;
576 // inbound-rtp
577 graph.inbound_rtp_id = "RTCInboundRTPVideoStream_4";
578 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
579 video_media_info.receivers[0].local_stats.push_back(
580 cricket::SsrcReceiverInfo());
581 video_media_info.receivers[0].local_stats[0].ssrc = 4;
582 video_media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
583 // transport
584 graph.transport_id = "RTCTransport_TransportName_1";
585 auto* video_media_channel =
586 pc_->AddVideoChannel("VideoMid", "TransportName");
587 video_media_channel->SetStats(video_media_info);
588 // track (sender)
589 graph.sender = stats_->SetupLocalTrackAndSender(
590 cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false);
591 graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
592 rtc::ToString<>(graph.sender->AttachmentId());
593 // track (receiver) and stream (remote stream)
594 graph.receiver = stats_->SetupRemoteTrackAndReceiver(
595 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
596 graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
597 rtc::ToString<>(graph.receiver->AttachmentId());
598 graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
599 // peer-connection
600 graph.peer_connection_id = "RTCPeerConnection";
601
602 // Expected stats graph:
603 //
604 // track (sender) stream (remote stream) ---> track (receiver)
605 // ^ ^
606 // | |
607 // outbound-rtp inbound-rtp ---------------+
608 // | | | |
609 // v v v v
610 // codec (send) transport codec (recv) peer-connection
611
612 // Verify the stats graph is set up correctly.
613 graph.full_report = stats_->GetStatsReport();
614 EXPECT_EQ(graph.full_report->size(), 9u);
615 EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
616 EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
617 EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
618 EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
619 EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
620 EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
621 EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
622 EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
623 EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
624 const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
625 ->cast_to<RTCOutboundRTPStreamStats>();
626 EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
627 EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
628 EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
629 const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
630 ->cast_to<RTCInboundRTPStreamStats>();
631 EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
632 EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
633 EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
634
635 return graph;
636 }
637
hbosc82f2e12016-09-05 01:36:50 -0700638 protected:
Steve Anton5b387312018-02-02 16:00:20 -0800639 rtc::ScopedFakeClock fake_clock_;
640 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
641 std::unique_ptr<RTCStatsCollectorWrapper> stats_;
hbosc82f2e12016-09-05 01:36:50 -0700642};
643
644TEST_F(RTCStatsCollectorTest, SingleCallback) {
645 rtc::scoped_refptr<const RTCStatsReport> result;
Steve Anton5b387312018-02-02 16:00:20 -0800646 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
hbosc82f2e12016-09-05 01:36:50 -0700647 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
648}
649
650TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
Steve Anton5b387312018-02-02 16:00:20 -0800651 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
652 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
653 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
654 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700655 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
656 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
657 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
Steve Anton5b387312018-02-02 16:00:20 -0800658
hbosc82f2e12016-09-05 01:36:50 -0700659 EXPECT_EQ(a.get(), b.get());
660 EXPECT_EQ(b.get(), c.get());
661}
662
663TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700664 // Caching should ensure |a| and |b| are the same report.
Steve Anton5b387312018-02-02 16:00:20 -0800665 rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
666 rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700667 EXPECT_EQ(a.get(), b.get());
668 // Invalidate cache by clearing it.
Steve Anton5b387312018-02-02 16:00:20 -0800669 stats_->stats_collector()->ClearCachedStatsReport();
670 rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700671 EXPECT_NE(b.get(), c.get());
672 // Invalidate cache by advancing time.
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200673 fake_clock_.AdvanceTime(TimeDelta::ms(51));
Steve Anton5b387312018-02-02 16:00:20 -0800674 rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700675 EXPECT_TRUE(d);
676 EXPECT_NE(c.get(), d.get());
677}
678
hbosc82f2e12016-09-05 01:36:50 -0700679TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
Steve Anton5b387312018-02-02 16:00:20 -0800680 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
681 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
682 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
hbosc82f2e12016-09-05 01:36:50 -0700683 // Cache is invalidated after 50 ms.
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200684 fake_clock_.AdvanceTime(TimeDelta::ms(51));
Steve Anton5b387312018-02-02 16:00:20 -0800685 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700686 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
687 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
688 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
689 EXPECT_EQ(a.get(), b.get());
690 // The act of doing |AdvanceTime| processes all messages. If this was not the
691 // case we might not require |c| to be fresher than |b|.
692 EXPECT_NE(c.get(), b.get());
693}
694
hbos6ab97ce2016-10-03 14:16:56 -0700695TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
Steve Anton5b387312018-02-02 16:00:20 -0800696 const char kTransportName[] = "transport";
697
698 pc_->AddVoiceChannel("audio", kTransportName);
699
hbos6ab97ce2016-10-03 14:16:56 -0700700 std::unique_ptr<CertificateInfo> local_certinfo =
701 CreateFakeCertificateAndInfoFromDers(
702 std::vector<std::string>({ "(local) single certificate" }));
Steve Anton5b387312018-02-02 16:00:20 -0800703 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
704
hbos6ab97ce2016-10-03 14:16:56 -0700705 std::unique_ptr<CertificateInfo> remote_certinfo =
706 CreateFakeCertificateAndInfoFromDers(
707 std::vector<std::string>({ "(remote) single certificate" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800708 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -0800709 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800710 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700711
Steve Anton5b387312018-02-02 16:00:20 -0800712 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ab97ce2016-10-03 14:16:56 -0700713
hbos23368e12016-12-21 04:29:17 -0800714 ExpectReportContainsCertificateInfo(report, *local_certinfo);
715 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700716}
717
hbos0adb8282016-11-23 02:32:06 -0800718TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
hbos0adb8282016-11-23 02:32:06 -0800719 // Audio
720 cricket::VoiceMediaInfo voice_media_info;
721
722 RtpCodecParameters inbound_audio_codec;
723 inbound_audio_codec.payload_type = 1;
deadbeefe702b302017-02-04 12:09:01 -0800724 inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
725 inbound_audio_codec.name = "opus";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100726 inbound_audio_codec.clock_rate = 1337;
hbos0adb8282016-11-23 02:32:06 -0800727 voice_media_info.receive_codecs.insert(
728 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
729
730 RtpCodecParameters outbound_audio_codec;
731 outbound_audio_codec.payload_type = 2;
deadbeefe702b302017-02-04 12:09:01 -0800732 outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
733 outbound_audio_codec.name = "isac";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100734 outbound_audio_codec.clock_rate = 1338;
hbos0adb8282016-11-23 02:32:06 -0800735 voice_media_info.send_codecs.insert(
736 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
737
Steve Anton57858b32018-02-15 15:19:50 -0800738 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800739 voice_media_channel->SetStats(voice_media_info);
hbos0adb8282016-11-23 02:32:06 -0800740
741 // Video
742 cricket::VideoMediaInfo video_media_info;
743
744 RtpCodecParameters inbound_video_codec;
745 inbound_video_codec.payload_type = 3;
deadbeefe702b302017-02-04 12:09:01 -0800746 inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
747 inbound_video_codec.name = "H264";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100748 inbound_video_codec.clock_rate = 1339;
hbos0adb8282016-11-23 02:32:06 -0800749 video_media_info.receive_codecs.insert(
750 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
751
752 RtpCodecParameters outbound_video_codec;
753 outbound_video_codec.payload_type = 4;
deadbeefe702b302017-02-04 12:09:01 -0800754 outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
755 outbound_video_codec.name = "VP8";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100756 outbound_video_codec.clock_rate = 1340;
hbos0adb8282016-11-23 02:32:06 -0800757 video_media_info.send_codecs.insert(
758 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
759
Steve Anton57858b32018-02-15 15:19:50 -0800760 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800761 video_media_channel->SetStats(video_media_info);
hbos0adb8282016-11-23 02:32:06 -0800762
Steve Anton5b387312018-02-02 16:00:20 -0800763 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0adb8282016-11-23 02:32:06 -0800764
Steve Anton57858b32018-02-15 15:19:50 -0800765 RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1",
766 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800767 expected_inbound_audio_codec.payload_type = 1;
hbos13f54b22017-02-28 06:56:04 -0800768 expected_inbound_audio_codec.mime_type = "audio/opus";
hbos0adb8282016-11-23 02:32:06 -0800769 expected_inbound_audio_codec.clock_rate = 1337;
770
Steve Anton57858b32018-02-15 15:19:50 -0800771 RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
772 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800773 expected_outbound_audio_codec.payload_type = 2;
hbos13f54b22017-02-28 06:56:04 -0800774 expected_outbound_audio_codec.mime_type = "audio/isac";
hbos0adb8282016-11-23 02:32:06 -0800775 expected_outbound_audio_codec.clock_rate = 1338;
776
Steve Anton57858b32018-02-15 15:19:50 -0800777 RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
778 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800779 expected_inbound_video_codec.payload_type = 3;
hbos13f54b22017-02-28 06:56:04 -0800780 expected_inbound_video_codec.mime_type = "video/H264";
hbos0adb8282016-11-23 02:32:06 -0800781 expected_inbound_video_codec.clock_rate = 1339;
782
Steve Anton57858b32018-02-15 15:19:50 -0800783 RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
784 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800785 expected_outbound_video_codec.payload_type = 4;
hbos13f54b22017-02-28 06:56:04 -0800786 expected_outbound_video_codec.mime_type = "video/VP8";
hbos0adb8282016-11-23 02:32:06 -0800787 expected_outbound_video_codec.clock_rate = 1340;
788
nissec8ee8822017-01-18 07:20:55 -0800789 ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800790 EXPECT_EQ(expected_inbound_audio_codec,
791 report->Get(expected_inbound_audio_codec.id())->cast_to<
792 RTCCodecStats>());
793
nissec8ee8822017-01-18 07:20:55 -0800794 ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800795 EXPECT_EQ(expected_outbound_audio_codec,
796 report->Get(expected_outbound_audio_codec.id())->cast_to<
797 RTCCodecStats>());
798
nissec8ee8822017-01-18 07:20:55 -0800799 ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800800 EXPECT_EQ(expected_inbound_video_codec,
801 report->Get(expected_inbound_video_codec.id())->cast_to<
802 RTCCodecStats>());
803
nissec8ee8822017-01-18 07:20:55 -0800804 ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800805 EXPECT_EQ(expected_outbound_video_codec,
806 report->Get(expected_outbound_video_codec.id())->cast_to<
807 RTCCodecStats>());
808}
809
hbos6ab97ce2016-10-03 14:16:56 -0700810TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
Steve Anton5b387312018-02-02 16:00:20 -0800811 const char kAudioTransport[] = "audio";
812 const char kVideoTransport[] = "video";
813
814 pc_->AddVoiceChannel("audio", kAudioTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700815 std::unique_ptr<CertificateInfo> audio_local_certinfo =
816 CreateFakeCertificateAndInfoFromDers(
817 std::vector<std::string>({ "(local) audio" }));
Steve Anton5b387312018-02-02 16:00:20 -0800818 pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700819 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
820 CreateFakeCertificateAndInfoFromDers(
821 std::vector<std::string>({ "(remote) audio" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800822 pc_->SetRemoteCertChain(
823 kAudioTransport,
824 audio_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700825
Steve Anton5b387312018-02-02 16:00:20 -0800826 pc_->AddVideoChannel("video", kVideoTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700827 std::unique_ptr<CertificateInfo> video_local_certinfo =
828 CreateFakeCertificateAndInfoFromDers(
829 std::vector<std::string>({ "(local) video" }));
Steve Anton5b387312018-02-02 16:00:20 -0800830 pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700831 std::unique_ptr<CertificateInfo> video_remote_certinfo =
832 CreateFakeCertificateAndInfoFromDers(
833 std::vector<std::string>({ "(remote) video" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800834 pc_->SetRemoteCertChain(
835 kVideoTransport,
836 video_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700837
Steve Anton5b387312018-02-02 16:00:20 -0800838 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800839 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
840 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
841 ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
842 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700843}
844
845TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
Steve Anton5b387312018-02-02 16:00:20 -0800846 const char kTransportName[] = "transport";
847
848 pc_->AddVoiceChannel("audio", kTransportName);
849
hbos6ab97ce2016-10-03 14:16:56 -0700850 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800851 CreateFakeCertificateAndInfoFromDers(
852 {"(local) this", "(local) is", "(local) a", "(local) chain"});
853 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
854
hbos6ab97ce2016-10-03 14:16:56 -0700855 std::unique_ptr<CertificateInfo> remote_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800856 CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
857 "(remote) another",
858 "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800859 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -0800860 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800861 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700862
Steve Anton5b387312018-02-02 16:00:20 -0800863 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800864 ExpectReportContainsCertificateInfo(report, *local_certinfo);
865 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700866}
867
hboscc555c52016-10-18 12:48:31 -0700868TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
Steve Anton5b387312018-02-02 16:00:20 -0800869 pc_->AddSctpDataChannel(new MockDataChannel(0, "MockDataChannel0",
870 DataChannelInterface::kConnecting,
871 "udp", 1, 2, 3, 4));
hbosdbb64d82016-12-21 01:57:46 -0800872 RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0);
873 expected_data_channel0.label = "MockDataChannel0";
874 expected_data_channel0.protocol = "udp";
875 expected_data_channel0.datachannelid = 0;
876 expected_data_channel0.state = "connecting";
877 expected_data_channel0.messages_sent = 1;
878 expected_data_channel0.bytes_sent = 2;
879 expected_data_channel0.messages_received = 3;
880 expected_data_channel0.bytes_received = 4;
881
Steve Anton5b387312018-02-02 16:00:20 -0800882 pc_->AddSctpDataChannel(new MockDataChannel(
Steve Antonbe5e2082018-01-24 15:29:17 -0800883 1, "MockDataChannel1", DataChannelInterface::kOpen, "tcp", 5, 6, 7, 8));
hbosdbb64d82016-12-21 01:57:46 -0800884 RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0);
885 expected_data_channel1.label = "MockDataChannel1";
886 expected_data_channel1.protocol = "tcp";
887 expected_data_channel1.datachannelid = 1;
888 expected_data_channel1.state = "open";
889 expected_data_channel1.messages_sent = 5;
890 expected_data_channel1.bytes_sent = 6;
891 expected_data_channel1.messages_received = 7;
892 expected_data_channel1.bytes_received = 8;
893
Steve Anton5b387312018-02-02 16:00:20 -0800894 pc_->AddSctpDataChannel(new MockDataChannel(2, "MockDataChannel2",
895 DataChannelInterface::kClosing,
896 "udp", 9, 10, 11, 12));
hbosdbb64d82016-12-21 01:57:46 -0800897 RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0);
898 expected_data_channel2.label = "MockDataChannel2";
899 expected_data_channel2.protocol = "udp";
900 expected_data_channel2.datachannelid = 2;
901 expected_data_channel2.state = "closing";
902 expected_data_channel2.messages_sent = 9;
903 expected_data_channel2.bytes_sent = 10;
904 expected_data_channel2.messages_received = 11;
905 expected_data_channel2.bytes_received = 12;
906
Steve Anton5b387312018-02-02 16:00:20 -0800907 pc_->AddSctpDataChannel(new MockDataChannel(3, "MockDataChannel3",
908 DataChannelInterface::kClosed,
909 "tcp", 13, 14, 15, 16));
hbosdbb64d82016-12-21 01:57:46 -0800910 RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0);
911 expected_data_channel3.label = "MockDataChannel3";
912 expected_data_channel3.protocol = "tcp";
913 expected_data_channel3.datachannelid = 3;
914 expected_data_channel3.state = "closed";
915 expected_data_channel3.messages_sent = 13;
916 expected_data_channel3.bytes_sent = 14;
917 expected_data_channel3.messages_received = 15;
918 expected_data_channel3.bytes_received = 16;
hboscc555c52016-10-18 12:48:31 -0700919
Steve Anton5b387312018-02-02 16:00:20 -0800920 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
921
hbosdbb64d82016-12-21 01:57:46 -0800922 ASSERT_TRUE(report->Get(expected_data_channel0.id()));
923 EXPECT_EQ(expected_data_channel0,
924 report->Get(expected_data_channel0.id())->cast_to<
925 RTCDataChannelStats>());
926 ASSERT_TRUE(report->Get(expected_data_channel1.id()));
927 EXPECT_EQ(expected_data_channel1,
928 report->Get(expected_data_channel1.id())->cast_to<
929 RTCDataChannelStats>());
930 ASSERT_TRUE(report->Get(expected_data_channel2.id()));
931 EXPECT_EQ(expected_data_channel2,
932 report->Get(expected_data_channel2.id())->cast_to<
933 RTCDataChannelStats>());
934 ASSERT_TRUE(report->Get(expected_data_channel3.id()));
935 EXPECT_EQ(expected_data_channel3,
936 report->Get(expected_data_channel3.id())->cast_to<
937 RTCDataChannelStats>());
hboscc555c52016-10-18 12:48:31 -0700938}
939
hbosab9f6e42016-10-07 02:18:47 -0700940TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
941 // Candidates in the first transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -0800942 std::unique_ptr<cricket::Candidate> a_local_host =
943 CreateFakeCandidate("1.2.3.4", 5, "a_local_host's protocol",
944 rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0);
hbosc42ba322016-12-21 03:31:45 -0800945 RTCLocalIceCandidateStats expected_a_local_host(
946 "RTCIceCandidate_" + a_local_host->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800947 expected_a_local_host.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -0800948 expected_a_local_host.network_type = "vpn";
hbosc42ba322016-12-21 03:31:45 -0800949 expected_a_local_host.ip = "1.2.3.4";
950 expected_a_local_host.port = 5;
951 expected_a_local_host.protocol = "a_local_host's protocol";
952 expected_a_local_host.candidate_type = "host";
953 expected_a_local_host.priority = 0;
hbosc3a2b7f2017-01-02 04:46:15 -0800954 EXPECT_FALSE(*expected_a_local_host.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800955
hbosab9f6e42016-10-07 02:18:47 -0700956 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800957 "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
958 cricket::STUN_PORT_TYPE, 1);
hbosc42ba322016-12-21 03:31:45 -0800959 RTCRemoteIceCandidateStats expected_a_remote_srflx(
960 "RTCIceCandidate_" + a_remote_srflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800961 expected_a_remote_srflx.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -0800962 expected_a_remote_srflx.ip = "6.7.8.9";
963 expected_a_remote_srflx.port = 10;
964 expected_a_remote_srflx.protocol = "remote_srflx's protocol";
965 expected_a_remote_srflx.candidate_type = "srflx";
966 expected_a_remote_srflx.priority = 1;
hbosd17a5a72017-01-02 08:09:59 -0800967 expected_a_remote_srflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800968 EXPECT_TRUE(*expected_a_remote_srflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800969
hbosab9f6e42016-10-07 02:18:47 -0700970 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800971 "11.12.13.14", 15, "a_local_prflx's protocol", rtc::ADAPTER_TYPE_CELLULAR,
972 cricket::PRFLX_PORT_TYPE, 2);
hbosc42ba322016-12-21 03:31:45 -0800973 RTCLocalIceCandidateStats expected_a_local_prflx(
974 "RTCIceCandidate_" + a_local_prflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800975 expected_a_local_prflx.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -0800976 expected_a_local_prflx.network_type = "cellular";
hbosc42ba322016-12-21 03:31:45 -0800977 expected_a_local_prflx.ip = "11.12.13.14";
978 expected_a_local_prflx.port = 15;
979 expected_a_local_prflx.protocol = "a_local_prflx's protocol";
980 expected_a_local_prflx.candidate_type = "prflx";
981 expected_a_local_prflx.priority = 2;
hbosd17a5a72017-01-02 08:09:59 -0800982 expected_a_local_prflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800983 EXPECT_FALSE(*expected_a_local_prflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800984
hbosab9f6e42016-10-07 02:18:47 -0700985 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800986 "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
987 cricket::RELAY_PORT_TYPE, 3);
hbosc42ba322016-12-21 03:31:45 -0800988 RTCRemoteIceCandidateStats expected_a_remote_relay(
989 "RTCIceCandidate_" + a_remote_relay->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800990 expected_a_remote_relay.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -0800991 expected_a_remote_relay.ip = "16.17.18.19";
992 expected_a_remote_relay.port = 20;
993 expected_a_remote_relay.protocol = "a_remote_relay's protocol";
994 expected_a_remote_relay.candidate_type = "relay";
995 expected_a_remote_relay.priority = 3;
hbosd17a5a72017-01-02 08:09:59 -0800996 expected_a_remote_relay.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800997 EXPECT_TRUE(*expected_a_remote_relay.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800998
hbosab9f6e42016-10-07 02:18:47 -0700999 // Candidates in the second transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -08001000 std::unique_ptr<cricket::Candidate> b_local =
1001 CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
1002 rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 03:31:45 -08001003 RTCLocalIceCandidateStats expected_b_local(
1004 "RTCIceCandidate_" + b_local->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001005 expected_b_local.transport_id = "RTCTransport_b_0";
Gary Liu37e489c2017-11-21 10:49:36 -08001006 expected_b_local.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -08001007 expected_b_local.ip = "42.42.42.42";
1008 expected_b_local.port = 42;
1009 expected_b_local.protocol = "b_local's protocol";
1010 expected_b_local.candidate_type = "host";
1011 expected_b_local.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001012 expected_b_local.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001013 EXPECT_FALSE(*expected_b_local.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001014
hbosab9f6e42016-10-07 02:18:47 -07001015 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001016 "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1017 cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 03:31:45 -08001018 RTCRemoteIceCandidateStats expected_b_remote(
1019 "RTCIceCandidate_" + b_remote->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001020 expected_b_remote.transport_id = "RTCTransport_b_0";
hbosc42ba322016-12-21 03:31:45 -08001021 expected_b_remote.ip = "42.42.42.42";
1022 expected_b_remote.port = 42;
1023 expected_b_remote.protocol = "b_remote's protocol";
1024 expected_b_remote.candidate_type = "host";
1025 expected_b_remote.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001026 expected_b_remote.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001027 EXPECT_TRUE(*expected_b_remote.is_remote);
hbosab9f6e42016-10-07 02:18:47 -07001028
hbosab9f6e42016-10-07 02:18:47 -07001029 cricket::TransportChannelStats a_transport_channel_stats;
1030 a_transport_channel_stats.connection_infos.push_back(
1031 cricket::ConnectionInfo());
1032 a_transport_channel_stats.connection_infos[0].local_candidate =
1033 *a_local_host.get();
1034 a_transport_channel_stats.connection_infos[0].remote_candidate =
1035 *a_remote_srflx.get();
1036 a_transport_channel_stats.connection_infos.push_back(
1037 cricket::ConnectionInfo());
1038 a_transport_channel_stats.connection_infos[1].local_candidate =
1039 *a_local_prflx.get();
1040 a_transport_channel_stats.connection_infos[1].remote_candidate =
1041 *a_remote_relay.get();
Steve Anton5b387312018-02-02 16:00:20 -08001042
1043 pc_->AddVoiceChannel("audio", "a");
1044 pc_->SetTransportStats("a", a_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -07001045
1046 cricket::TransportChannelStats b_transport_channel_stats;
1047 b_transport_channel_stats.connection_infos.push_back(
1048 cricket::ConnectionInfo());
1049 b_transport_channel_stats.connection_infos[0].local_candidate =
1050 *b_local.get();
1051 b_transport_channel_stats.connection_infos[0].remote_candidate =
1052 *b_remote.get();
hbosab9f6e42016-10-07 02:18:47 -07001053
Steve Anton5b387312018-02-02 16:00:20 -08001054 pc_->AddVideoChannel("video", "b");
1055 pc_->SetTransportStats("b", b_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -07001056
Steve Anton5b387312018-02-02 16:00:20 -08001057 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbosc42ba322016-12-21 03:31:45 -08001058
hbosb4e426e2017-01-02 09:59:31 -08001059 ASSERT_TRUE(report->Get(expected_a_local_host.id()));
hbosc42ba322016-12-21 03:31:45 -08001060 EXPECT_EQ(expected_a_local_host,
1061 report->Get(expected_a_local_host.id())->cast_to<
1062 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001063 ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
hbosc42ba322016-12-21 03:31:45 -08001064 EXPECT_EQ(expected_a_remote_srflx,
1065 report->Get(expected_a_remote_srflx.id())->cast_to<
1066 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001067 ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
hbosc42ba322016-12-21 03:31:45 -08001068 EXPECT_EQ(expected_a_local_prflx,
1069 report->Get(expected_a_local_prflx.id())->cast_to<
1070 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001071 ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
hbosc42ba322016-12-21 03:31:45 -08001072 EXPECT_EQ(expected_a_remote_relay,
1073 report->Get(expected_a_remote_relay.id())->cast_to<
1074 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001075 ASSERT_TRUE(report->Get(expected_b_local.id()));
hbosc42ba322016-12-21 03:31:45 -08001076 EXPECT_EQ(expected_b_local,
1077 report->Get(expected_b_local.id())->cast_to<
1078 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001079 ASSERT_TRUE(report->Get(expected_b_remote.id()));
hbosc42ba322016-12-21 03:31:45 -08001080 EXPECT_EQ(expected_b_remote,
1081 report->Get(expected_b_remote.id())->cast_to<
1082 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001083 EXPECT_TRUE(report->Get("RTCTransport_a_0"));
1084 EXPECT_TRUE(report->Get("RTCTransport_b_0"));
hbosab9f6e42016-10-07 02:18:47 -07001085}
1086
hbosc47a0c32016-10-11 14:54:49 -07001087TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
Steve Anton5b387312018-02-02 16:00:20 -08001088 const char kTransportName[] = "transport";
hbos338f78a2017-02-07 06:41:21 -08001089
Gary Liu37e489c2017-11-21 10:49:36 -08001090 std::unique_ptr<cricket::Candidate> local_candidate =
1091 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1092 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -07001093 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001094 "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1095 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -07001096
hbosc47a0c32016-10-11 14:54:49 -07001097 cricket::ConnectionInfo connection_info;
hbos338f78a2017-02-07 06:41:21 -08001098 connection_info.best_connection = false;
hbosc47a0c32016-10-11 14:54:49 -07001099 connection_info.local_candidate = *local_candidate.get();
1100 connection_info.remote_candidate = *remote_candidate.get();
1101 connection_info.writable = true;
1102 connection_info.sent_total_bytes = 42;
1103 connection_info.recv_total_bytes = 1234;
hbosbf8d3e52017-02-28 06:34:47 -08001104 connection_info.total_round_trip_time_ms = 0;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001105 connection_info.current_round_trip_time_ms = rtc::nullopt;
hbosd82f5122016-12-09 04:12:39 -08001106 connection_info.recv_ping_requests = 2020;
hbose448dd52016-12-12 01:22:53 -08001107 connection_info.sent_ping_requests_total = 2020;
1108 connection_info.sent_ping_requests_before_first_response = 2000;
hbosc47a0c32016-10-11 14:54:49 -07001109 connection_info.recv_ping_responses = 4321;
1110 connection_info.sent_ping_responses = 1000;
hbos06495bc2017-01-02 08:08:18 -08001111 connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
1112 connection_info.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -08001113 connection_info.nominated = false;
hbosc47a0c32016-10-11 14:54:49 -07001114
1115 cricket::TransportChannelStats transport_channel_stats;
hbos0583b282016-11-30 01:50:14 -08001116 transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
hbosc47a0c32016-10-11 14:54:49 -07001117 transport_channel_stats.connection_infos.push_back(connection_info);
hbosc47a0c32016-10-11 14:54:49 -07001118
Steve Anton5b387312018-02-02 16:00:20 -08001119 pc_->AddVideoChannel("video", kTransportName);
1120 pc_->SetTransportStats(kTransportName, transport_channel_stats);
hbosc47a0c32016-10-11 14:54:49 -07001121
Steve Anton5b387312018-02-02 16:00:20 -08001122 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -08001123
1124 RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" +
1125 local_candidate->id() + "_" +
1126 remote_candidate->id(),
1127 report->timestamp_us());
1128 expected_pair.transport_id =
1129 "RTCTransport_transport_" +
1130 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1131 expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
1132 expected_pair.remote_candidate_id =
1133 "RTCIceCandidate_" + remote_candidate->id();
hbos06495bc2017-01-02 08:08:18 -08001134 expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1135 expected_pair.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -08001136 expected_pair.nominated = false;
hbos0583b282016-11-30 01:50:14 -08001137 expected_pair.writable = true;
1138 expected_pair.bytes_sent = 42;
1139 expected_pair.bytes_received = 1234;
hbosbf8d3e52017-02-28 06:34:47 -08001140 expected_pair.total_round_trip_time = 0.0;
hbosd82f5122016-12-09 04:12:39 -08001141 expected_pair.requests_received = 2020;
hbose448dd52016-12-12 01:22:53 -08001142 expected_pair.requests_sent = 2000;
hbos0583b282016-11-30 01:50:14 -08001143 expected_pair.responses_received = 4321;
1144 expected_pair.responses_sent = 1000;
hbose448dd52016-12-12 01:22:53 -08001145 expected_pair.consent_requests_sent = (2020 - 2000);
hbosbf8d3e52017-02-28 06:34:47 -08001146 // |expected_pair.current_round_trip_time| should be undefined because the
1147 // current RTT is not set.
hbos338f78a2017-02-07 06:41:21 -08001148 // |expected_pair.available_[outgoing/incoming]_bitrate| should be undefined
1149 // because is is not the current pair.
hbos0583b282016-11-30 01:50:14 -08001150
hbosdbb64d82016-12-21 01:57:46 -08001151 ASSERT_TRUE(report->Get(expected_pair.id()));
hbos0583b282016-11-30 01:50:14 -08001152 EXPECT_EQ(
1153 expected_pair,
1154 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
hbosb4e426e2017-01-02 09:59:31 -08001155 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
hbos0583b282016-11-30 01:50:14 -08001156
hbos92eaec62017-02-27 01:38:08 -08001157 // Set nominated and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001158 transport_channel_stats.connection_infos[0].nominated = true;
1159 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1160 report = stats_->GetFreshStatsReport();
hbos92eaec62017-02-27 01:38:08 -08001161 expected_pair.nominated = true;
1162 ASSERT_TRUE(report->Get(expected_pair.id()));
1163 EXPECT_EQ(
1164 expected_pair,
1165 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1166 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1167
hbosbf8d3e52017-02-28 06:34:47 -08001168 // Set round trip times and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001169 transport_channel_stats.connection_infos[0].total_round_trip_time_ms = 7331;
1170 transport_channel_stats.connection_infos[0].current_round_trip_time_ms = 1337;
1171 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1172 report = stats_->GetFreshStatsReport();
hbosbf8d3e52017-02-28 06:34:47 -08001173 expected_pair.total_round_trip_time = 7.331;
1174 expected_pair.current_round_trip_time = 1.337;
1175 ASSERT_TRUE(report->Get(expected_pair.id()));
1176 EXPECT_EQ(
1177 expected_pair,
1178 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1179 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1180
hbos338f78a2017-02-07 06:41:21 -08001181 // Make pair the current pair, clear bandwidth and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001182 transport_channel_stats.connection_infos[0].best_connection = true;
1183 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1184 report = stats_->GetFreshStatsReport();
hbos338f78a2017-02-07 06:41:21 -08001185 // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
1186 // undefined because bandwidth is not set.
1187 ASSERT_TRUE(report->Get(expected_pair.id()));
1188 EXPECT_EQ(
1189 expected_pair,
1190 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1191 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1192
1193 // Set bandwidth and "GetStats" again.
stefanf79ade12017-06-02 06:44:03 -07001194 webrtc::Call::Stats call_stats;
1195 const int kSendBandwidth = 888;
1196 call_stats.send_bandwidth_bps = kSendBandwidth;
1197 const int kRecvBandwidth = 999;
1198 call_stats.recv_bandwidth_bps = kRecvBandwidth;
Steve Anton5b387312018-02-02 16:00:20 -08001199 pc_->SetCallStats(call_stats);
1200 report = stats_->GetFreshStatsReport();
stefanf79ade12017-06-02 06:44:03 -07001201 expected_pair.available_outgoing_bitrate = kSendBandwidth;
1202 expected_pair.available_incoming_bitrate = kRecvBandwidth;
hbos338f78a2017-02-07 06:41:21 -08001203 ASSERT_TRUE(report->Get(expected_pair.id()));
1204 EXPECT_EQ(
1205 expected_pair,
1206 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1207 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1208
hbosc42ba322016-12-21 03:31:45 -08001209 RTCLocalIceCandidateStats expected_local_candidate(
1210 *expected_pair.local_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001211 expected_local_candidate.transport_id = *expected_pair.transport_id;
Gary Liu37e489c2017-11-21 10:49:36 -08001212 expected_local_candidate.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -08001213 expected_local_candidate.ip = "42.42.42.42";
1214 expected_local_candidate.port = 42;
1215 expected_local_candidate.protocol = "protocol";
1216 expected_local_candidate.candidate_type = "host";
1217 expected_local_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001218 expected_local_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001219 EXPECT_FALSE(*expected_local_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001220 ASSERT_TRUE(report->Get(expected_local_candidate.id()));
1221 EXPECT_EQ(expected_local_candidate,
1222 report->Get(expected_local_candidate.id())->cast_to<
1223 RTCLocalIceCandidateStats>());
1224
1225 RTCRemoteIceCandidateStats expected_remote_candidate(
1226 *expected_pair.remote_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001227 expected_remote_candidate.transport_id = *expected_pair.transport_id;
hbosc42ba322016-12-21 03:31:45 -08001228 expected_remote_candidate.ip = "42.42.42.42";
1229 expected_remote_candidate.port = 42;
1230 expected_remote_candidate.protocol = "protocol";
1231 expected_remote_candidate.candidate_type = "host";
1232 expected_remote_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001233 expected_remote_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001234 EXPECT_TRUE(*expected_remote_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001235 ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
1236 EXPECT_EQ(expected_remote_candidate,
1237 report->Get(expected_remote_candidate.id())->cast_to<
1238 RTCRemoteIceCandidateStats>());
hbosc47a0c32016-10-11 14:54:49 -07001239}
1240
hbosd565b732016-08-30 14:04:35 -07001241TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosd565b732016-08-30 14:04:35 -07001242 {
Steve Anton5b387312018-02-02 16:00:20 -08001243 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001244 RTCPeerConnectionStats expected("RTCPeerConnection",
1245 report->timestamp_us());
1246 expected.data_channels_opened = 0;
1247 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001248 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001249 EXPECT_EQ(expected,
1250 report->Get("RTCPeerConnection")->cast_to<
1251 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001252 }
1253
hbos82ebe022016-11-14 01:41:09 -08001254 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create(
1255 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001256 pc_->SignalDataChannelCreated()(dummy_channel_a.get());
hbos82ebe022016-11-14 01:41:09 -08001257 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create(
1258 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001259 pc_->SignalDataChannelCreated()(dummy_channel_b.get());
hbosd565b732016-08-30 14:04:35 -07001260
hbos82ebe022016-11-14 01:41:09 -08001261 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1262 // Closing a channel that is not opened should not affect the counts.
1263 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1264
hbosd565b732016-08-30 14:04:35 -07001265 {
Steve Anton5b387312018-02-02 16:00:20 -08001266 rtc::scoped_refptr<const RTCStatsReport> report =
1267 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001268 RTCPeerConnectionStats expected("RTCPeerConnection",
1269 report->timestamp_us());
1270 expected.data_channels_opened = 1;
1271 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001272 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001273 EXPECT_EQ(expected,
1274 report->Get("RTCPeerConnection")->cast_to<
1275 RTCPeerConnectionStats>());
1276 }
1277
1278 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1279 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1280
1281 {
Steve Anton5b387312018-02-02 16:00:20 -08001282 rtc::scoped_refptr<const RTCStatsReport> report =
1283 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001284 RTCPeerConnectionStats expected("RTCPeerConnection",
1285 report->timestamp_us());
1286 expected.data_channels_opened = 2;
1287 expected.data_channels_closed = 1;
hbosdbb64d82016-12-21 01:57:46 -08001288 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001289 EXPECT_EQ(expected,
1290 report->Get("RTCPeerConnection")->cast_to<
1291 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001292 }
hbos5bf9def2017-03-20 03:14:14 -07001293
1294 // Re-opening a data channel (or opening a new data channel that is re-using
1295 // the same address in memory) should increase the opened count.
1296 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1297
1298 {
Steve Anton5b387312018-02-02 16:00:20 -08001299 rtc::scoped_refptr<const RTCStatsReport> report =
1300 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001301 RTCPeerConnectionStats expected("RTCPeerConnection",
1302 report->timestamp_us());
1303 expected.data_channels_opened = 3;
1304 expected.data_channels_closed = 1;
1305 ASSERT_TRUE(report->Get("RTCPeerConnection"));
1306 EXPECT_EQ(expected,
1307 report->Get("RTCPeerConnection")->cast_to<
1308 RTCPeerConnectionStats>());
1309 }
1310
1311 dummy_channel_a->SignalClosed(dummy_channel_a.get());
1312 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1313
1314 {
Steve Anton5b387312018-02-02 16:00:20 -08001315 rtc::scoped_refptr<const RTCStatsReport> report =
1316 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001317 RTCPeerConnectionStats expected("RTCPeerConnection",
1318 report->timestamp_us());
1319 expected.data_channels_opened = 3;
1320 expected.data_channels_closed = 3;
1321 ASSERT_TRUE(report->Get("RTCPeerConnection"));
1322 EXPECT_EQ(expected,
1323 report->Get("RTCPeerConnection")->cast_to<
1324 RTCPeerConnectionStats>());
1325 }
hbosd565b732016-08-30 14:04:35 -07001326}
1327
hbos09bc1282016-11-08 06:29:22 -08001328TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001329 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
hbos09bc1282016-11-08 06:29:22 -08001330 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001331 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001332 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001333
1334 // Local audio track
hbos9e302742017-01-20 02:47:10 -08001335 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
1336 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
1337 MediaStreamTrackInterface::kEnded);
1338 local_stream->AddTrack(static_cast<AudioTrackInterface*>(
1339 local_audio_track.get()));
1340
1341 cricket::VoiceSenderInfo voice_sender_info_ssrc1;
1342 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1343 voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
1344 voice_sender_info_ssrc1.audio_level = 32767;
zsteine76bd3a2017-07-14 12:17:49 -07001345 voice_sender_info_ssrc1.total_input_energy = 0.25;
1346 voice_sender_info_ssrc1.total_input_duration = 0.5;
Ivo Creusen56d46092017-11-24 17:29:59 +01001347 voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
1348 voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
hbos9e302742017-01-20 02:47:10 -08001349
Steve Anton5b387312018-02-02 16:00:20 -08001350 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001351 {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001352 {}, {}, {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001353
Steve Anton5b387312018-02-02 16:00:20 -08001354 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001355
1356 RTCMediaStreamStats expected_local_stream(
1357 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001358 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001359 expected_local_stream.track_ids = {
1360 IdForType<RTCMediaStreamTrackStats>(report)};
1361 ASSERT_TRUE(report->Get(expected_local_stream.id()))
1362 << "Did not find " << expected_local_stream.id() << " in "
1363 << report->ToJson();
1364 EXPECT_EQ(
1365 expected_local_stream,
1366 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1367
1368 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
1369 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1370 RTCMediaStreamTrackKind::kAudio);
1371 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
1372 expected_local_audio_track_ssrc1.remote_source = false;
1373 expected_local_audio_track_ssrc1.ended = true;
1374 expected_local_audio_track_ssrc1.detached = false;
1375 expected_local_audio_track_ssrc1.audio_level = 1.0;
1376 expected_local_audio_track_ssrc1.total_audio_energy = 0.25;
1377 expected_local_audio_track_ssrc1.total_samples_duration = 0.5;
1378 expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
1379 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
1380 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
1381 << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
1382 << report->ToJson();
1383 EXPECT_EQ(expected_local_audio_track_ssrc1,
1384 report->Get(expected_local_audio_track_ssrc1.id())
1385 ->cast_to<RTCMediaStreamTrackStats>());
1386}
1387
1388TEST_F(RTCStatsCollectorTest,
1389 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001390 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001391 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001392 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001393
hbos09bc1282016-11-08 06:29:22 -08001394 // Remote audio track
hbos9e302742017-01-20 02:47:10 -08001395 rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
1396 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
1397 MediaStreamTrackInterface::kLive);
1398 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(
1399 remote_audio_track.get()));
1400
1401 cricket::VoiceReceiverInfo voice_receiver_info;
1402 voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
1403 voice_receiver_info.local_stats[0].ssrc = 3;
1404 voice_receiver_info.audio_level = 16383;
zsteine76bd3a2017-07-14 12:17:49 -07001405 voice_receiver_info.total_output_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001406 voice_receiver_info.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001407 voice_receiver_info.total_output_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001408 voice_receiver_info.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001409 voice_receiver_info.concealment_events = 12;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001410 voice_receiver_info.jitter_buffer_delay_seconds = 3456;
hbos9e302742017-01-20 02:47:10 -08001411
Steve Anton5b387312018-02-02 16:00:20 -08001412 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001413 {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
1414 {}, {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001415
Steve Anton5b387312018-02-02 16:00:20 -08001416 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001417
hbos09bc1282016-11-08 06:29:22 -08001418 RTCMediaStreamStats expected_remote_stream(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001419 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001420 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001421 expected_remote_stream.track_ids =
1422 std::vector<std::string>({IdForType<RTCMediaStreamTrackStats>(report)});
1423 ASSERT_TRUE(report->Get(expected_remote_stream.id()))
1424 << "Did not find " << expected_remote_stream.id() << " in "
1425 << report->ToJson();
hbos09bc1282016-11-08 06:29:22 -08001426 EXPECT_EQ(expected_remote_stream,
1427 report->Get(expected_remote_stream.id())->cast_to<
1428 RTCMediaStreamStats>());
1429
hbos09bc1282016-11-08 06:29:22 -08001430 RTCMediaStreamTrackStats expected_remote_audio_track(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001431 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1432 RTCMediaStreamTrackKind::kAudio);
hbos09bc1282016-11-08 06:29:22 -08001433 expected_remote_audio_track.track_identifier = remote_audio_track->id();
1434 expected_remote_audio_track.remote_source = true;
1435 expected_remote_audio_track.ended = false;
1436 expected_remote_audio_track.detached = false;
hbos9e302742017-01-20 02:47:10 -08001437 expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
zsteine76bd3a2017-07-14 12:17:49 -07001438 expected_remote_audio_track.total_audio_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001439 expected_remote_audio_track.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001440 expected_remote_audio_track.total_samples_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001441 expected_remote_audio_track.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001442 expected_remote_audio_track.concealment_events = 12;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001443 expected_remote_audio_track.jitter_buffer_delay = 3456;
hbosdbb64d82016-12-21 01:57:46 -08001444 ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
hbos09bc1282016-11-08 06:29:22 -08001445 EXPECT_EQ(expected_remote_audio_track,
1446 report->Get(expected_remote_audio_track.id())->cast_to<
1447 RTCMediaStreamTrackStats>());
1448}
1449
1450TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001451 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
hbos09bc1282016-11-08 06:29:22 -08001452 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001453 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001454 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001455
1456 // Local video track
hbos9e302742017-01-20 02:47:10 -08001457 rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
1458 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
1459 MediaStreamTrackInterface::kLive);
1460 local_stream->AddTrack(static_cast<VideoTrackInterface*>(
1461 local_video_track.get()));
hbos09bc1282016-11-08 06:29:22 -08001462
hbos9e302742017-01-20 02:47:10 -08001463 cricket::VideoSenderInfo video_sender_info_ssrc1;
1464 video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1465 video_sender_info_ssrc1.local_stats[0].ssrc = 1;
1466 video_sender_info_ssrc1.send_frame_width = 1234;
1467 video_sender_info_ssrc1.send_frame_height = 4321;
hbosfefe0762017-01-20 06:14:25 -08001468 video_sender_info_ssrc1.frames_encoded = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001469 video_sender_info_ssrc1.huge_frames_sent = 1;
hbos9e302742017-01-20 02:47:10 -08001470
Steve Anton5b387312018-02-02 16:00:20 -08001471 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001472 {}, {},
1473 {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001474 {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001475
Steve Anton5b387312018-02-02 16:00:20 -08001476 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001477
1478 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1479 ASSERT_EQ(1, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1480 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1481 ASSERT_EQ(1, stats_of_track_type.size())
1482 << "Wrong number of tracks in " << report->ToJson();
1483
1484 RTCMediaStreamStats expected_local_stream(stats_of_my_type[0]->id(),
1485 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001486 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001487 expected_local_stream.track_ids =
1488 std::vector<std::string>({stats_of_track_type[0]->id()});
1489 ASSERT_TRUE(report->Get(expected_local_stream.id()));
1490 EXPECT_EQ(
1491 expected_local_stream,
1492 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1493
1494 RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
1495 stats_of_track_type[0]->id(), report->timestamp_us(),
1496 RTCMediaStreamTrackKind::kVideo);
1497 expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
1498 expected_local_video_track_ssrc1.remote_source = false;
1499 expected_local_video_track_ssrc1.ended = false;
1500 expected_local_video_track_ssrc1.detached = false;
1501 expected_local_video_track_ssrc1.frame_width = 1234;
1502 expected_local_video_track_ssrc1.frame_height = 4321;
1503 expected_local_video_track_ssrc1.frames_sent = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001504 expected_local_video_track_ssrc1.huge_frames_sent = 1;
Harald Alvestranda3dab842018-01-14 09:18:58 +01001505 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
1506 EXPECT_EQ(expected_local_video_track_ssrc1,
1507 report->Get(expected_local_video_track_ssrc1.id())
1508 ->cast_to<RTCMediaStreamTrackStats>());
1509}
1510
1511TEST_F(RTCStatsCollectorTest,
1512 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001513 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001514 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001515 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001516
hbos9e302742017-01-20 02:47:10 -08001517 // Remote video track with values
1518 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
1519 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
1520 MediaStreamTrackInterface::kEnded);
1521 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(
1522 remote_video_track_ssrc3.get()));
1523
1524 cricket::VideoReceiverInfo video_receiver_info_ssrc3;
1525 video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
1526 video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
1527 video_receiver_info_ssrc3.frame_width = 6789;
1528 video_receiver_info_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001529 video_receiver_info_ssrc3.frames_received = 1000;
1530 video_receiver_info_ssrc3.frames_decoded = 995;
1531 video_receiver_info_ssrc3.frames_rendered = 990;
hbos9e302742017-01-20 02:47:10 -08001532
Steve Anton5b387312018-02-02 16:00:20 -08001533 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001534 {}, {}, {},
Harald Alvestrandc72af932018-01-11 17:18:19 +01001535 {std::make_pair(remote_video_track_ssrc3.get(),
Harald Alvestranda3dab842018-01-14 09:18:58 +01001536 video_receiver_info_ssrc3)},
1537 {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001538
Steve Anton5b387312018-02-02 16:00:20 -08001539 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001540
Harald Alvestranda3dab842018-01-14 09:18:58 +01001541 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1542 ASSERT_EQ(1, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1543 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1544 ASSERT_EQ(1, stats_of_track_type.size())
1545 << "Wrong number of tracks in " << report->ToJson();
1546 ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
hbos09bc1282016-11-08 06:29:22 -08001547
Harald Alvestranda3dab842018-01-14 09:18:58 +01001548 RTCMediaStreamStats expected_remote_stream(stats_of_my_type[0]->id(),
1549 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001550 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001551 expected_remote_stream.track_ids =
1552 std::vector<std::string>({stats_of_track_type[0]->id()});
hbosdbb64d82016-12-21 01:57:46 -08001553 ASSERT_TRUE(report->Get(expected_remote_stream.id()));
hbos09bc1282016-11-08 06:29:22 -08001554 EXPECT_EQ(expected_remote_stream,
1555 report->Get(expected_remote_stream.id())->cast_to<
1556 RTCMediaStreamStats>());
1557
hbos9e302742017-01-20 02:47:10 -08001558 RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001559 stats_of_track_type[0]->id(), report->timestamp_us(),
1560 RTCMediaStreamTrackKind::kVideo);
hbos9e302742017-01-20 02:47:10 -08001561 expected_remote_video_track_ssrc3.track_identifier =
1562 remote_video_track_ssrc3->id();
1563 expected_remote_video_track_ssrc3.remote_source = true;
1564 expected_remote_video_track_ssrc3.ended = true;
1565 expected_remote_video_track_ssrc3.detached = false;
1566 expected_remote_video_track_ssrc3.frame_width = 6789;
1567 expected_remote_video_track_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001568 expected_remote_video_track_ssrc3.frames_received = 1000;
1569 expected_remote_video_track_ssrc3.frames_decoded = 995;
1570 expected_remote_video_track_ssrc3.frames_dropped = 1000 - 990;
hbos9e302742017-01-20 02:47:10 -08001571 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
1572 EXPECT_EQ(expected_remote_video_track_ssrc3,
1573 report->Get(expected_remote_video_track_ssrc3.id())->cast_to<
1574 RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 06:29:22 -08001575}
1576
hboseeafe942016-11-01 03:00:17 -07001577TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
hboseeafe942016-11-01 03:00:17 -07001578 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001579
hboseeafe942016-11-01 03:00:17 -07001580 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1581 voice_media_info.receivers[0].local_stats.push_back(
1582 cricket::SsrcReceiverInfo());
1583 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001584 voice_media_info.receivers[0].packets_lost = -1; // Signed per RFC3550
hboseeafe942016-11-01 03:00:17 -07001585 voice_media_info.receivers[0].packets_rcvd = 2;
1586 voice_media_info.receivers[0].bytes_rcvd = 3;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001587 voice_media_info.receivers[0].codec_payload_type = 42;
hboseeafe942016-11-01 03:00:17 -07001588 voice_media_info.receivers[0].jitter_ms = 4500;
1589 voice_media_info.receivers[0].fraction_lost = 5.5f;
hbos0adb8282016-11-23 02:32:06 -08001590
1591 RtpCodecParameters codec_parameters;
1592 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001593 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1594 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001595 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001596 voice_media_info.receive_codecs.insert(
1597 std::make_pair(codec_parameters.payload_type, codec_parameters));
1598
Steve Anton57858b32018-02-15 15:19:50 -08001599 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001600 voice_media_channel->SetStats(voice_media_info);
Henrik Boström5b3541f2018-03-19 13:52:56 +01001601 stats_->SetupRemoteTrackAndReceiver(
1602 cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 03:00:17 -07001603
Steve Anton5b387312018-02-02 16:00:20 -08001604 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001605
Harald Alvestranda3dab842018-01-14 09:18:58 +01001606 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1607 ASSERT_EQ(1, stats_of_track_type.size());
1608
hboseeafe942016-11-01 03:00:17 -07001609 RTCInboundRTPStreamStats expected_audio(
1610 "RTCInboundRTPAudioStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001611 expected_audio.ssrc = 1;
hboseeafe942016-11-01 03:00:17 -07001612 expected_audio.is_remote = false;
1613 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001614 expected_audio.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001615 expected_audio.transport_id = "RTCTransport_TransportName_1";
1616 expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42";
hboseeafe942016-11-01 03:00:17 -07001617 expected_audio.packets_received = 2;
1618 expected_audio.bytes_received = 3;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001619 expected_audio.packets_lost = -1;
hboseeafe942016-11-01 03:00:17 -07001620 expected_audio.jitter = 4.5;
1621 expected_audio.fraction_lost = 5.5;
nissec8ee8822017-01-18 07:20:55 -08001622 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001623 EXPECT_EQ(
1624 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1625 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001626 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001627 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1628 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hboseeafe942016-11-01 03:00:17 -07001629}
1630
1631TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
hboseeafe942016-11-01 03:00:17 -07001632 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001633
hboseeafe942016-11-01 03:00:17 -07001634 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1635 video_media_info.receivers[0].local_stats.push_back(
1636 cricket::SsrcReceiverInfo());
1637 video_media_info.receivers[0].local_stats[0].ssrc = 1;
1638 video_media_info.receivers[0].packets_rcvd = 2;
hbos02cd4d62016-12-09 04:19:44 -08001639 video_media_info.receivers[0].packets_lost = 42;
hboseeafe942016-11-01 03:00:17 -07001640 video_media_info.receivers[0].bytes_rcvd = 3;
1641 video_media_info.receivers[0].fraction_lost = 4.5f;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001642 video_media_info.receivers[0].codec_payload_type = 42;
hbos820f5782016-11-22 03:16:50 -08001643 video_media_info.receivers[0].firs_sent = 5;
1644 video_media_info.receivers[0].plis_sent = 6;
1645 video_media_info.receivers[0].nacks_sent = 7;
hbos6769c492017-01-02 08:35:13 -08001646 video_media_info.receivers[0].frames_decoded = 8;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001647 video_media_info.receivers[0].qp_sum = rtc::nullopt;
hbos0adb8282016-11-23 02:32:06 -08001648
1649 RtpCodecParameters codec_parameters;
1650 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001651 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1652 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001653 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001654 video_media_info.receive_codecs.insert(
1655 std::make_pair(codec_parameters.payload_type, codec_parameters));
1656
Steve Anton57858b32018-02-15 15:19:50 -08001657 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001658 video_media_channel->SetStats(video_media_info);
Henrik Boström5b3541f2018-03-19 13:52:56 +01001659 stats_->SetupRemoteTrackAndReceiver(
1660 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 03:00:17 -07001661
Steve Anton5b387312018-02-02 16:00:20 -08001662 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001663
hbos820f5782016-11-22 03:16:50 -08001664 RTCInboundRTPStreamStats expected_video(
hboseeafe942016-11-01 03:00:17 -07001665 "RTCInboundRTPVideoStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001666 expected_video.ssrc = 1;
hbos820f5782016-11-22 03:16:50 -08001667 expected_video.is_remote = false;
1668 expected_video.media_type = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001669 expected_video.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001670 expected_video.transport_id = "RTCTransport_TransportName_1";
1671 expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42";
hbos820f5782016-11-22 03:16:50 -08001672 expected_video.fir_count = 5;
1673 expected_video.pli_count = 6;
1674 expected_video.nack_count = 7;
1675 expected_video.packets_received = 2;
1676 expected_video.bytes_received = 3;
hbos02cd4d62016-12-09 04:19:44 -08001677 expected_video.packets_lost = 42;
hbos820f5782016-11-22 03:16:50 -08001678 expected_video.fraction_lost = 4.5;
hbos6769c492017-01-02 08:35:13 -08001679 expected_video.frames_decoded = 8;
hbosa51d4f32017-02-16 05:34:48 -08001680 // |expected_video.qp_sum| should be undefined.
hboseeafe942016-11-01 03:00:17 -07001681
nissec8ee8822017-01-18 07:20:55 -08001682 ASSERT_TRUE(report->Get(expected_video.id()));
hbosa51d4f32017-02-16 05:34:48 -08001683 EXPECT_EQ(
1684 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1685 expected_video);
hboseeafe942016-11-01 03:00:17 -07001686
hbosa51d4f32017-02-16 05:34:48 -08001687 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001688 video_media_info.receivers[0].qp_sum = 9;
hbosa51d4f32017-02-16 05:34:48 -08001689 expected_video.qp_sum = 9;
Steve Anton5b387312018-02-02 16:00:20 -08001690 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001691
Steve Anton5b387312018-02-02 16:00:20 -08001692 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001693
1694 ASSERT_TRUE(report->Get(expected_video.id()));
1695 EXPECT_EQ(
1696 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1697 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08001698 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08001699 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbosa51d4f32017-02-16 05:34:48 -08001700 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hboseeafe942016-11-01 03:00:17 -07001701}
1702
hbos6ded1902016-11-01 01:50:46 -07001703TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
hbos6ded1902016-11-01 01:50:46 -07001704 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001705
hbos6ded1902016-11-01 01:50:46 -07001706 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1707 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1708 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1709 voice_media_info.senders[0].packets_sent = 2;
1710 voice_media_info.senders[0].bytes_sent = 3;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001711 voice_media_info.senders[0].codec_payload_type = 42;
hbos0adb8282016-11-23 02:32:06 -08001712
1713 RtpCodecParameters codec_parameters;
1714 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001715 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1716 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001717 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001718 voice_media_info.send_codecs.insert(
1719 std::make_pair(codec_parameters.payload_type, codec_parameters));
1720
Steve Anton57858b32018-02-15 15:19:50 -08001721 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001722 voice_media_channel->SetStats(voice_media_info);
1723 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
1724 "LocalAudioTrackID", 1, true);
hbos6ded1902016-11-01 01:50:46 -07001725
Steve Anton5b387312018-02-02 16:00:20 -08001726 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001727
1728 RTCOutboundRTPStreamStats expected_audio(
1729 "RTCOutboundRTPAudioStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001730 expected_audio.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001731 expected_audio.is_remote = false;
1732 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001733 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001734 expected_audio.transport_id = "RTCTransport_TransportName_1";
1735 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001736 expected_audio.packets_sent = 2;
1737 expected_audio.bytes_sent = 3;
hboscd195be2017-02-07 08:31:27 -08001738
hboscd195be2017-02-07 08:31:27 -08001739 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001740 EXPECT_EQ(
1741 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1742 expected_audio);
skvladed02c6d2017-02-07 10:45:31 -08001743
hbosa51d4f32017-02-16 05:34:48 -08001744 ASSERT_TRUE(report->Get(expected_audio.id()));
1745 EXPECT_EQ(
1746 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1747 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001748 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001749 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1750 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001751}
1752
1753TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
hbos6ded1902016-11-01 01:50:46 -07001754 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001755
hbos6ded1902016-11-01 01:50:46 -07001756 video_media_info.senders.push_back(cricket::VideoSenderInfo());
1757 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1758 video_media_info.senders[0].local_stats[0].ssrc = 1;
1759 video_media_info.senders[0].firs_rcvd = 2;
1760 video_media_info.senders[0].plis_rcvd = 3;
1761 video_media_info.senders[0].nacks_rcvd = 4;
1762 video_media_info.senders[0].packets_sent = 5;
1763 video_media_info.senders[0].bytes_sent = 6;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001764 video_media_info.senders[0].codec_payload_type = 42;
hbos6769c492017-01-02 08:35:13 -08001765 video_media_info.senders[0].frames_encoded = 8;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001766 video_media_info.senders[0].qp_sum = rtc::nullopt;
hbos0adb8282016-11-23 02:32:06 -08001767
1768 RtpCodecParameters codec_parameters;
1769 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001770 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1771 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001772 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001773 video_media_info.send_codecs.insert(
1774 std::make_pair(codec_parameters.payload_type, codec_parameters));
1775
Steve Anton57858b32018-02-15 15:19:50 -08001776 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001777 video_media_channel->SetStats(video_media_info);
1778 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
1779 "LocalVideoTrackID", 1, true);
hbos6ded1902016-11-01 01:50:46 -07001780
Steve Anton5b387312018-02-02 16:00:20 -08001781 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001782
Harald Alvestranda3dab842018-01-14 09:18:58 +01001783 auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
1784 ASSERT_EQ(1, stats_of_my_type.size());
1785 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1786 ASSERT_EQ(1, stats_of_track_type.size());
1787
1788 RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
1789 report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001790 expected_video.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001791 expected_video.is_remote = false;
1792 expected_video.media_type = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001793 expected_video.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001794 expected_video.transport_id = "RTCTransport_TransportName_1";
1795 expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001796 expected_video.fir_count = 2;
1797 expected_video.pli_count = 3;
1798 expected_video.nack_count = 4;
1799 expected_video.packets_sent = 5;
1800 expected_video.bytes_sent = 6;
skvladed02c6d2017-02-07 10:45:31 -08001801 expected_video.frames_encoded = 8;
hbosa7a9be12017-03-01 01:02:45 -08001802 // |expected_video.qp_sum| should be undefined.
hboscd195be2017-02-07 08:31:27 -08001803 ASSERT_TRUE(report->Get(expected_video.id()));
Harald Alvestranda3dab842018-01-14 09:18:58 +01001804
hbosa51d4f32017-02-16 05:34:48 -08001805 EXPECT_EQ(
1806 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
1807 expected_video);
skvladed02c6d2017-02-07 10:45:31 -08001808
hbosa51d4f32017-02-16 05:34:48 -08001809 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001810 video_media_info.senders[0].qp_sum = 9;
hbosa51d4f32017-02-16 05:34:48 -08001811 expected_video.qp_sum = 9;
Steve Anton5b387312018-02-02 16:00:20 -08001812 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001813
Steve Anton5b387312018-02-02 16:00:20 -08001814 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001815
1816 ASSERT_TRUE(report->Get(expected_video.id()));
1817 EXPECT_EQ(
1818 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
1819 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08001820 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08001821 EXPECT_TRUE(report->Get(*expected_video.transport_id));
1822 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001823}
1824
hbos2fa7c672016-10-24 04:00:05 -07001825TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
Steve Anton5b387312018-02-02 16:00:20 -08001826 const char kTransportName[] = "transport";
1827
1828 pc_->AddVoiceChannel("audio", kTransportName);
1829
Gary Liu37e489c2017-11-21 10:49:36 -08001830 std::unique_ptr<cricket::Candidate> rtp_local_candidate =
1831 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1832 cricket::LOCAL_PORT_TYPE, 42);
hbos2fa7c672016-10-24 04:00:05 -07001833 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
1834 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08001835 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
1836 42);
hbos2fa7c672016-10-24 04:00:05 -07001837 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
Gary Liu37e489c2017-11-21 10:49:36 -08001838 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
hbos2fa7c672016-10-24 04:00:05 -07001839 cricket::LOCAL_PORT_TYPE, 42);
1840 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
1841 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08001842 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
1843 42);
hbos2fa7c672016-10-24 04:00:05 -07001844
hbos2fa7c672016-10-24 04:00:05 -07001845 cricket::ConnectionInfo rtp_connection_info;
1846 rtp_connection_info.best_connection = false;
1847 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
1848 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
1849 rtp_connection_info.sent_total_bytes = 42;
1850 rtp_connection_info.recv_total_bytes = 1337;
1851 cricket::TransportChannelStats rtp_transport_channel_stats;
1852 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1853 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
hbos7064d592017-01-16 07:38:02 -08001854 rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
Steve Anton5b387312018-02-02 16:00:20 -08001855 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001856
1857 // Get stats without RTCP, an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08001858 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -08001859
1860 RTCTransportStats expected_rtp_transport(
1861 "RTCTransport_transport_" +
1862 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP),
1863 report->timestamp_us());
1864 expected_rtp_transport.bytes_sent = 42;
1865 expected_rtp_transport.bytes_received = 1337;
hbos7064d592017-01-16 07:38:02 -08001866 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
hbos0583b282016-11-30 01:50:14 -08001867
hbosdbb64d82016-12-21 01:57:46 -08001868 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001869 EXPECT_EQ(
1870 expected_rtp_transport,
1871 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001872
1873 cricket::ConnectionInfo rtcp_connection_info;
1874 rtcp_connection_info.best_connection = false;
1875 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
1876 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
1877 rtcp_connection_info.sent_total_bytes = 1337;
1878 rtcp_connection_info.recv_total_bytes = 42;
1879 cricket::TransportChannelStats rtcp_transport_channel_stats;
1880 rtcp_transport_channel_stats.component =
1881 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
1882 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
hbos7064d592017-01-16 07:38:02 -08001883 rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTING;
Steve Anton5b387312018-02-02 16:00:20 -08001884 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
1885 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001886
hbos2fa7c672016-10-24 04:00:05 -07001887 // Get stats with RTCP and without an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08001888 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001889
1890 RTCTransportStats expected_rtcp_transport(
1891 "RTCTransport_transport_" +
1892 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
1893 report->timestamp_us());
1894 expected_rtcp_transport.bytes_sent = 1337;
1895 expected_rtcp_transport.bytes_received = 42;
hbos7064d592017-01-16 07:38:02 -08001896 expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
hbos0583b282016-11-30 01:50:14 -08001897
1898 expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
1899
hbosdbb64d82016-12-21 01:57:46 -08001900 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001901 EXPECT_EQ(
1902 expected_rtp_transport,
1903 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001904 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001905 EXPECT_EQ(
1906 expected_rtcp_transport,
1907 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001908
hbos7064d592017-01-16 07:38:02 -08001909 // Get stats with an active connection (selected candidate pair).
Steve Anton5b387312018-02-02 16:00:20 -08001910 rtcp_transport_channel_stats.connection_infos[0].best_connection = true;
1911 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
1912 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001913
Steve Anton5b387312018-02-02 16:00:20 -08001914 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001915
hbos0583b282016-11-30 01:50:14 -08001916 expected_rtcp_transport.selected_candidate_pair_id =
1917 "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" +
1918 rtcp_remote_candidate->id();
1919
hbosdbb64d82016-12-21 01:57:46 -08001920 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001921 EXPECT_EQ(
1922 expected_rtp_transport,
1923 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001924 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001925 EXPECT_EQ(
1926 expected_rtcp_transport,
1927 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001928
1929 // Get stats with certificates.
1930 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -08001931 CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
1932 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
hbos2fa7c672016-10-24 04:00:05 -07001933 std::unique_ptr<CertificateInfo> remote_certinfo =
1934 CreateFakeCertificateAndInfoFromDers(
Steve Anton5b387312018-02-02 16:00:20 -08001935 {"(remote) local", "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -08001936 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -08001937 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -08001938 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos2fa7c672016-10-24 04:00:05 -07001939
Steve Anton5b387312018-02-02 16:00:20 -08001940 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001941
1942 expected_rtp_transport.local_certificate_id =
1943 "RTCCertificate_" + local_certinfo->fingerprints[0];
1944 expected_rtp_transport.remote_certificate_id =
1945 "RTCCertificate_" + remote_certinfo->fingerprints[0];
1946
1947 expected_rtcp_transport.local_certificate_id =
1948 *expected_rtp_transport.local_certificate_id;
1949 expected_rtcp_transport.remote_certificate_id =
1950 *expected_rtp_transport.remote_certificate_id;
1951
hbosdbb64d82016-12-21 01:57:46 -08001952 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001953 EXPECT_EQ(
1954 expected_rtp_transport,
1955 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001956 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001957 EXPECT_EQ(
1958 expected_rtcp_transport,
1959 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001960}
1961
Harald Alvestrand89061872018-01-02 14:08:34 +01001962TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
Harald Alvestrand89061872018-01-02 14:08:34 +01001963 cricket::VoiceMediaInfo voice_media_info;
1964
1965 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1966 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1967 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1968 voice_media_info.senders[0].packets_sent = 2;
1969 voice_media_info.senders[0].bytes_sent = 3;
1970 voice_media_info.senders[0].codec_payload_type = 42;
1971
1972 RtpCodecParameters codec_parameters;
1973 codec_parameters.payload_type = 42;
1974 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1975 codec_parameters.name = "dummy";
1976 codec_parameters.clock_rate = 0;
1977 voice_media_info.send_codecs.insert(
1978 std::make_pair(codec_parameters.payload_type, codec_parameters));
1979
Steve Anton5b387312018-02-02 16:00:20 -08001980 // Emulates the case where AddTrack is used without an associated MediaStream
Steve Anton57858b32018-02-15 15:19:50 -08001981 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001982 voice_media_channel->SetStats(voice_media_info);
1983 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
1984 "LocalAudioTrackID", 1, false);
Harald Alvestrand89061872018-01-02 14:08:34 +01001985
Steve Anton5b387312018-02-02 16:00:20 -08001986 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestrand89061872018-01-02 14:08:34 +01001987
1988 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
1989 report->timestamp_us());
1990 expected_audio.ssrc = 1;
1991 expected_audio.is_remote = false;
1992 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001993 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001994 expected_audio.transport_id = "RTCTransport_TransportName_1";
1995 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
Harald Alvestrand89061872018-01-02 14:08:34 +01001996 expected_audio.packets_sent = 2;
1997 expected_audio.bytes_sent = 3;
1998
1999 ASSERT_TRUE(report->Get(expected_audio.id()));
2000 EXPECT_EQ(
2001 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2002 expected_audio);
Harald Alvestrand89061872018-01-02 14:08:34 +01002003 EXPECT_TRUE(report->Get(*expected_audio.track_id));
2004 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2005 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2006}
2007
Henrik Boström5b3541f2018-03-19 13:52:56 +01002008TEST_F(RTCStatsCollectorTest, GetStatsWithSenderSelector) {
2009 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2010 // Expected stats graph when filtered by sender:
2011 //
2012 // track (sender)
2013 // ^
2014 // |
2015 // outbound-rtp
2016 // | |
2017 // v v
2018 // codec (send) transport
2019 rtc::scoped_refptr<const RTCStatsReport> sender_report =
2020 stats_->GetStatsReportWithSenderSelector(graph.sender);
2021 EXPECT_TRUE(sender_report);
2022 EXPECT_EQ(sender_report->timestamp_us(), graph.full_report->timestamp_us());
2023 EXPECT_EQ(sender_report->size(), 4u);
2024 EXPECT_TRUE(sender_report->Get(graph.send_codec_id));
2025 EXPECT_FALSE(sender_report->Get(graph.recv_codec_id));
2026 EXPECT_TRUE(sender_report->Get(graph.outbound_rtp_id));
2027 EXPECT_FALSE(sender_report->Get(graph.inbound_rtp_id));
2028 EXPECT_TRUE(sender_report->Get(graph.transport_id));
2029 EXPECT_TRUE(sender_report->Get(graph.sender_track_id));
2030 EXPECT_FALSE(sender_report->Get(graph.receiver_track_id));
2031 EXPECT_FALSE(sender_report->Get(graph.remote_stream_id));
2032 EXPECT_FALSE(sender_report->Get(graph.peer_connection_id));
2033}
2034
2035TEST_F(RTCStatsCollectorTest, GetStatsWithReceiverSelector) {
2036 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2037 // Expected stats graph when filtered by receiver:
2038 //
2039 // track (receiver)
2040 // ^
2041 // |
2042 // inbound-rtp ---------------+
2043 // | |
2044 // v v
2045 // transport codec (recv)
2046 rtc::scoped_refptr<const RTCStatsReport> receiver_report =
2047 stats_->GetStatsReportWithReceiverSelector(graph.receiver);
2048 EXPECT_TRUE(receiver_report);
2049 EXPECT_EQ(receiver_report->size(), 4u);
2050 EXPECT_EQ(receiver_report->timestamp_us(), graph.full_report->timestamp_us());
2051 EXPECT_FALSE(receiver_report->Get(graph.send_codec_id));
2052 EXPECT_TRUE(receiver_report->Get(graph.recv_codec_id));
2053 EXPECT_FALSE(receiver_report->Get(graph.outbound_rtp_id));
2054 EXPECT_TRUE(receiver_report->Get(graph.inbound_rtp_id));
2055 EXPECT_TRUE(receiver_report->Get(graph.transport_id));
2056 EXPECT_FALSE(receiver_report->Get(graph.sender_track_id));
2057 EXPECT_TRUE(receiver_report->Get(graph.receiver_track_id));
2058 EXPECT_FALSE(receiver_report->Get(graph.remote_stream_id));
2059 EXPECT_FALSE(receiver_report->Get(graph.peer_connection_id));
2060}
2061
2062TEST_F(RTCStatsCollectorTest, GetStatsWithNullSenderSelector) {
2063 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2064 rtc::scoped_refptr<const RTCStatsReport> empty_report =
2065 stats_->GetStatsReportWithSenderSelector(nullptr);
2066 EXPECT_TRUE(empty_report);
2067 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2068 EXPECT_EQ(empty_report->size(), 0u);
2069}
2070
2071TEST_F(RTCStatsCollectorTest, GetStatsWithNullReceiverSelector) {
2072 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2073 rtc::scoped_refptr<const RTCStatsReport> empty_report =
2074 stats_->GetStatsReportWithReceiverSelector(nullptr);
2075 EXPECT_TRUE(empty_report);
2076 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2077 EXPECT_EQ(empty_report->size(), 0u);
2078}
2079
Harald Alvestrand89061872018-01-02 14:08:34 +01002080// When the PC has not had SetLocalDescription done, tracks all have
2081// SSRC 0, meaning "unconnected".
Harald Alvestrandb8e12012018-01-23 15:28:16 +01002082// In this state, we report on track stats, but not RTP stats.
2083TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
Harald Alvestrand89061872018-01-02 14:08:34 +01002084 rtc::scoped_refptr<MediaStreamTrackInterface> track =
2085 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2086 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08002087 rtc::scoped_refptr<MockRtpSenderInternal> sender =
2088 CreateMockSender(track, 0, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08002089 pc_->AddSender(sender);
2090
2091 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2092
Harald Alvestrand89061872018-01-02 14:08:34 +01002093 std::vector<const RTCMediaStreamTrackStats*> track_stats =
2094 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Harald Alvestrandb8e12012018-01-23 15:28:16 +01002095 EXPECT_EQ(1, track_stats.size());
Steve Anton5b387312018-02-02 16:00:20 -08002096
Harald Alvestrandb8e12012018-01-23 15:28:16 +01002097 std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
2098 report->GetStatsOfType<RTCRTPStreamStats>();
2099 EXPECT_EQ(0, rtp_stream_stats.size());
Harald Alvestrand89061872018-01-02 14:08:34 +01002100}
2101
Harald Alvestrand76d29522018-01-30 14:43:29 +01002102TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
2103 rtc::scoped_refptr<MediaStreamTrackInterface> track =
2104 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2105 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08002106 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Harald Alvestrand76d29522018-01-30 14:43:29 +01002107 CreateMockSender(track, 4711, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08002108 pc_->AddSender(sender);
2109
Harald Alvestrand76d29522018-01-30 14:43:29 +01002110 // We do not generate any matching voice_sender_info stats.
Steve Anton5b387312018-02-02 16:00:20 -08002111 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2112
Harald Alvestrand76d29522018-01-30 14:43:29 +01002113 std::vector<const RTCMediaStreamTrackStats*> track_stats =
2114 report->GetStatsOfType<RTCMediaStreamTrackStats>();
2115 EXPECT_EQ(1, track_stats.size());
2116}
2117
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002118// Used for test below, to test calling GetStatsReport during a callback.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002119class RecursiveCallback : public RTCStatsCollectorCallback {
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002120 public:
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002121 explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002122
2123 void OnStatsDelivered(
2124 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
2125 stats_->GetStatsReport();
2126 called_ = true;
2127 }
2128
2129 bool called() const { return called_; }
2130
2131 private:
2132 RTCStatsCollectorWrapper* stats_;
2133 bool called_ = false;
2134};
2135
2136// Test that nothing bad happens if a callback causes GetStatsReport to be
2137// called again recursively. Regression test for crbug.com/webrtc/8973.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002138TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
2139 rtc::scoped_refptr<RecursiveCallback> callback1(
2140 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
2141 rtc::scoped_refptr<RecursiveCallback> callback2(
2142 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002143 stats_->stats_collector()->GetStatsReport(callback1);
2144 stats_->stats_collector()->GetStatsReport(callback2);
2145 EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
2146 EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
2147}
2148
Steve Anton5b387312018-02-02 16:00:20 -08002149class RTCTestStats : public RTCStats {
hbosc82f2e12016-09-05 01:36:50 -07002150 public:
Steve Anton5b387312018-02-02 16:00:20 -08002151 WEBRTC_RTCSTATS_DECL();
2152
2153 RTCTestStats(const std::string& id, int64_t timestamp_us)
2154 : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
2155
2156 RTCStatsMember<int32_t> dummy_stat;
2157};
2158
2159WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat);
2160
2161// Overrides the stats collection to verify thread usage and that the resulting
2162// partial reports are merged.
2163class FakeRTCStatsCollector : public RTCStatsCollector,
2164 public RTCStatsCollectorCallback {
2165 public:
2166 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
2167 PeerConnectionInternal* pc,
2168 int64_t cache_lifetime_us) {
2169 return rtc::scoped_refptr<FakeRTCStatsCollector>(
2170 new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
2171 cache_lifetime_us));
2172 }
2173
2174 // RTCStatsCollectorCallback implementation.
2175 void OnStatsDelivered(
2176 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
2177 EXPECT_TRUE(signaling_thread_->IsCurrent());
2178 rtc::CritScope cs(&lock_);
2179 delivered_report_ = report;
2180 }
2181
2182 void VerifyThreadUsageAndResultsMerging() {
2183 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
2184 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
2185 }
2186
2187 bool HasVerifiedResults() {
2188 EXPECT_TRUE(signaling_thread_->IsCurrent());
2189 rtc::CritScope cs(&lock_);
2190 if (!delivered_report_)
2191 return false;
2192 EXPECT_EQ(produced_on_signaling_thread_, 1);
2193 EXPECT_EQ(produced_on_network_thread_, 1);
2194
2195 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
2196 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
2197
2198 produced_on_signaling_thread_ = 0;
2199 produced_on_network_thread_ = 0;
2200 delivered_report_ = nullptr;
2201 return true;
hbosc82f2e12016-09-05 01:36:50 -07002202 }
2203
2204 protected:
Steve Anton5b387312018-02-02 16:00:20 -08002205 FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
2206 : RTCStatsCollector(pc, cache_lifetime),
2207 signaling_thread_(pc->signaling_thread()),
2208 worker_thread_(pc->worker_thread()),
2209 network_thread_(pc->network_thread()) {}
2210
2211 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
2212 EXPECT_TRUE(signaling_thread_->IsCurrent());
2213 {
2214 rtc::CritScope cs(&lock_);
2215 EXPECT_FALSE(delivered_report_);
2216 ++produced_on_signaling_thread_;
2217 }
2218
2219 rtc::scoped_refptr<RTCStatsReport> signaling_report =
2220 RTCStatsReport::Create(0);
2221 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
2222 new RTCTestStats("SignalingThreadStats", timestamp_us)));
2223 AddPartialResults(signaling_report);
2224 }
2225 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
2226 EXPECT_TRUE(network_thread_->IsCurrent());
2227 {
2228 rtc::CritScope cs(&lock_);
2229 EXPECT_FALSE(delivered_report_);
2230 ++produced_on_network_thread_;
2231 }
2232
2233 rtc::scoped_refptr<RTCStatsReport> network_report =
2234 RTCStatsReport::Create(0);
2235 network_report->AddStats(std::unique_ptr<const RTCStats>(
2236 new RTCTestStats("NetworkThreadStats", timestamp_us)));
2237 AddPartialResults(network_report);
2238 }
2239
2240 private:
2241 rtc::Thread* const signaling_thread_;
2242 rtc::Thread* const worker_thread_;
2243 rtc::Thread* const network_thread_;
2244
2245 rtc::CriticalSection lock_;
2246 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
2247 int produced_on_signaling_thread_ = 0;
2248 int produced_on_network_thread_ = 0;
hbosc82f2e12016-09-05 01:36:50 -07002249};
2250
Steve Anton5b387312018-02-02 16:00:20 -08002251TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
2252 rtc::scoped_refptr<FakePeerConnectionForStats> pc(
2253 new rtc::RefCountedObject<FakePeerConnectionForStats>());
2254 rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
2255 FakeRTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec));
2256 stats_collector->VerifyThreadUsageAndResultsMerging();
hbosc82f2e12016-09-05 01:36:50 -07002257}
2258
2259} // namespace
2260
hbosd565b732016-08-30 14:04:35 -07002261} // namespace webrtc