blob: 8ec0929fd1d9b26ff515cf079da46209a4ba5e3b [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "p2p/base/p2pconstants.h"
22#include "p2p/base/port.h"
23#include "pc/mediastream.h"
24#include "pc/mediastreamtrack.h"
Steve Anton5b387312018-02-02 16:00:20 -080025#include "pc/rtcstatscollector.h"
26#include "pc/test/fakepeerconnectionforstats.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "pc/test/mock_datachannel.h"
Steve Anton57858b32018-02-15 15:19:50 -080028#include "pc/test/mock_rtpreceiverinternal.h"
29#include "pc/test/mock_rtpsenderinternal.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "pc/test/rtcstatsobtainer.h"
31#include "rtc_base/checks.h"
32#include "rtc_base/fakeclock.h"
33#include "rtc_base/fakesslidentity.h"
34#include "rtc_base/gunit.h"
35#include "rtc_base/logging.h"
Steve Anton5b387312018-02-02 16:00:20 -080036#include "rtc_base/ptr_util.h"
37#include "rtc_base/stringutils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020038#include "rtc_base/timedelta.h"
39#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
Steve Anton5b387312018-02-02 16:00:20 -0800302 rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
303 stats_collector_->ClearCachedStatsReport();
304 return GetStatsReport();
305 }
306
307 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
308 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
309 stats_collector_->GetStatsReport(callback);
310 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
311 int64_t after = rtc::TimeUTCMicros();
312 for (const RTCStats& stats : *callback->report()) {
313 EXPECT_LE(stats.timestamp_us(), after);
314 }
315 return callback->report();
hbosd565b732016-08-30 14:04:35 -0700316 }
317
hbos84abeb12017-01-16 06:16:44 -0800318 void SetupLocalTrackAndSender(cricket::MediaType media_type,
319 const std::string& track_id,
Harald Alvestrand89061872018-01-02 14:08:34 +0100320 uint32_t ssrc,
321 bool add_stream) {
Harald Alvestrand89061872018-01-02 14:08:34 +0100322 rtc::scoped_refptr<MediaStream> local_stream;
323 if (add_stream) {
Seth Hampson845e8782018-03-02 11:34:10 -0800324 local_stream = MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -0800325 pc_->mutable_local_streams()->AddStream(local_stream);
Harald Alvestrand89061872018-01-02 14:08:34 +0100326 }
hbos84abeb12017-01-16 06:16:44 -0800327
328 rtc::scoped_refptr<MediaStreamTrackInterface> track;
329 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800330 track = CreateFakeTrack(media_type, track_id,
331 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100332 if (add_stream) {
333 local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
334 }
hbos84abeb12017-01-16 06:16:44 -0800335 } else {
hbos9e302742017-01-20 02:47:10 -0800336 track = CreateFakeTrack(media_type, track_id,
337 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100338 if (add_stream) {
339 local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
340 }
hbos84abeb12017-01-16 06:16:44 -0800341 }
342
Steve Anton57858b32018-02-15 15:19:50 -0800343 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Harald Alvestranda3dab842018-01-14 09:18:58 +0100344 CreateMockSender(track, ssrc, 50, {});
Steve Anton5b387312018-02-02 16:00:20 -0800345 pc_->AddSender(sender);
hbos84abeb12017-01-16 06:16:44 -0800346 }
347
348 void SetupRemoteTrackAndReceiver(cricket::MediaType media_type,
349 const std::string& track_id,
350 uint32_t ssrc) {
hbos84abeb12017-01-16 06:16:44 -0800351 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -0800352 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -0800353 pc_->mutable_remote_streams()->AddStream(remote_stream);
hbos84abeb12017-01-16 06:16:44 -0800354
355 rtc::scoped_refptr<MediaStreamTrackInterface> track;
356 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800357 track = CreateFakeTrack(media_type, track_id,
358 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800359 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
360 } else {
hbos9e302742017-01-20 02:47:10 -0800361 track = CreateFakeTrack(media_type, track_id,
362 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800363 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
364 }
365
Steve Anton57858b32018-02-15 15:19:50 -0800366 rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
Harald Alvestrandc72af932018-01-11 17:18:19 +0100367 CreateMockReceiver(track, ssrc, 62);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100368 EXPECT_CALL(*receiver, streams())
369 .WillRepeatedly(
370 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
371 {remote_stream})));
Steve Anton5b387312018-02-02 16:00:20 -0800372 pc_->AddReceiver(receiver);
hbos84abeb12017-01-16 06:16:44 -0800373 }
374
hbos9e302742017-01-20 02:47:10 -0800375 // Attaches tracks to peer connections by configuring RTP senders and RTP
376 // receivers according to the tracks' pairings with
377 // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
378 // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
379 // be associated with one |[Voice/Video]ReceiverInfo|.
380 void CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +0100381 std::initializer_list<
382 std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
383 local_audio_track_info_pairs,
384 std::initializer_list<
385 std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
386 remote_audio_track_info_pairs,
387 std::initializer_list<
388 std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
389 local_video_track_info_pairs,
390 std::initializer_list<
391 std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
392 remote_video_track_info_pairs,
393 std::vector<std::string> local_stream_ids,
394 std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
Steve Anton5b387312018-02-02 16:00:20 -0800395 cricket::VoiceMediaInfo voice_media_info;
396 cricket::VideoMediaInfo video_media_info;
397
hbos9e302742017-01-20 02:47:10 -0800398 // Local audio tracks and voice sender infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100399 int attachment_id = 147;
hbos9e302742017-01-20 02:47:10 -0800400 for (auto& pair : local_audio_track_info_pairs) {
401 MediaStreamTrackInterface* local_audio_track = pair.first;
402 const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
403 RTC_DCHECK_EQ(local_audio_track->kind(),
404 MediaStreamTrackInterface::kAudioKind);
405
Steve Anton5b387312018-02-02 16:00:20 -0800406 voice_media_info.senders.push_back(voice_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800407 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Harald Alvestrandc72af932018-01-11 17:18:19 +0100408 rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
Harald Alvestranda3dab842018-01-14 09:18:58 +0100409 voice_sender_info.local_stats[0].ssrc, attachment_id++,
410 local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800411 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800412 }
Steve Anton5b387312018-02-02 16:00:20 -0800413
hbos9e302742017-01-20 02:47:10 -0800414 // Remote audio tracks and voice receiver infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100415 attachment_id = 181;
hbos9e302742017-01-20 02:47:10 -0800416 for (auto& pair : remote_audio_track_info_pairs) {
417 MediaStreamTrackInterface* remote_audio_track = pair.first;
418 const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
419 RTC_DCHECK_EQ(remote_audio_track->kind(),
420 MediaStreamTrackInterface::kAudioKind);
421
Steve Anton5b387312018-02-02 16:00:20 -0800422 voice_media_info.receivers.push_back(voice_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800423 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
424 CreateMockReceiver(
425 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
426 voice_receiver_info.local_stats[0].ssrc, attachment_id++);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100427 EXPECT_CALL(*rtp_receiver, streams())
428 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800429 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800430 }
Steve Anton5b387312018-02-02 16:00:20 -0800431
hbos9e302742017-01-20 02:47:10 -0800432 // Local video tracks and video sender infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100433 attachment_id = 151;
hbos9e302742017-01-20 02:47:10 -0800434 for (auto& pair : local_video_track_info_pairs) {
435 MediaStreamTrackInterface* local_video_track = pair.first;
436 const cricket::VideoSenderInfo& video_sender_info = pair.second;
437 RTC_DCHECK_EQ(local_video_track->kind(),
438 MediaStreamTrackInterface::kVideoKind);
439
Steve Anton5b387312018-02-02 16:00:20 -0800440 video_media_info.senders.push_back(video_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800441 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Harald Alvestrandc72af932018-01-11 17:18:19 +0100442 rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
Harald Alvestranda3dab842018-01-14 09:18:58 +0100443 video_sender_info.local_stats[0].ssrc, attachment_id++,
444 local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800445 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800446 }
Steve Anton5b387312018-02-02 16:00:20 -0800447
hbos9e302742017-01-20 02:47:10 -0800448 // Remote video tracks and video receiver infos
Harald Alvestrandc72af932018-01-11 17:18:19 +0100449 attachment_id = 191;
hbos9e302742017-01-20 02:47:10 -0800450 for (auto& pair : remote_video_track_info_pairs) {
451 MediaStreamTrackInterface* remote_video_track = pair.first;
452 const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
453 RTC_DCHECK_EQ(remote_video_track->kind(),
454 MediaStreamTrackInterface::kVideoKind);
455
Steve Anton5b387312018-02-02 16:00:20 -0800456 video_media_info.receivers.push_back(video_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800457 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
458 CreateMockReceiver(
459 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
460 video_receiver_info.local_stats[0].ssrc, attachment_id++);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100461 EXPECT_CALL(*rtp_receiver, streams())
462 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800463 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800464 }
hbos9e302742017-01-20 02:47:10 -0800465
Steve Anton5b387312018-02-02 16:00:20 -0800466 auto* voice_media_channel = pc_->AddVoiceChannel("audio", "transport");
467 voice_media_channel->SetStats(voice_media_info);
hbos9e302742017-01-20 02:47:10 -0800468
Steve Anton5b387312018-02-02 16:00:20 -0800469 auto* video_media_channel = pc_->AddVideoChannel("video", "transport");
470 video_media_channel->SetStats(video_media_info);
hbos9e302742017-01-20 02:47:10 -0800471 }
472
hbosd565b732016-08-30 14:04:35 -0700473 private:
Steve Anton5b387312018-02-02 16:00:20 -0800474 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
475 rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
hbosd565b732016-08-30 14:04:35 -0700476};
477
hbosc82f2e12016-09-05 01:36:50 -0700478class RTCStatsCollectorTest : public testing::Test {
479 public:
480 RTCStatsCollectorTest()
Steve Anton5b387312018-02-02 16:00:20 -0800481 : pc_(new rtc::RefCountedObject<FakePeerConnectionForStats>()),
482 stats_(new RTCStatsCollectorWrapper(pc_)) {}
hbosc82f2e12016-09-05 01:36:50 -0700483
hbos6ab97ce2016-10-03 14:16:56 -0700484 void ExpectReportContainsCertificateInfo(
485 const rtc::scoped_refptr<const RTCStatsReport>& report,
hbos23368e12016-12-21 04:29:17 -0800486 const CertificateInfo& certinfo) {
487 for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
488 RTCCertificateStats expected_certificate_stats(
489 "RTCCertificate_" + certinfo.fingerprints[i],
490 report->timestamp_us());
491 expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
492 expected_certificate_stats.fingerprint_algorithm = "sha-1";
493 expected_certificate_stats.base64_certificate = certinfo.pems[i];
494 if (i + 1 < certinfo.fingerprints.size()) {
495 expected_certificate_stats.issuer_certificate_id =
496 "RTCCertificate_" + certinfo.fingerprints[i + 1];
hbos6ab97ce2016-10-03 14:16:56 -0700497 }
hbos23368e12016-12-21 04:29:17 -0800498 ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
499 EXPECT_EQ(expected_certificate_stats,
500 report->Get(expected_certificate_stats.id())->cast_to<
501 RTCCertificateStats>());
hbos6ab97ce2016-10-03 14:16:56 -0700502 }
503 }
504
hbosc82f2e12016-09-05 01:36:50 -0700505 protected:
Steve Anton5b387312018-02-02 16:00:20 -0800506 rtc::ScopedFakeClock fake_clock_;
507 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
508 std::unique_ptr<RTCStatsCollectorWrapper> stats_;
hbosc82f2e12016-09-05 01:36:50 -0700509};
510
511TEST_F(RTCStatsCollectorTest, SingleCallback) {
512 rtc::scoped_refptr<const RTCStatsReport> result;
Steve Anton5b387312018-02-02 16:00:20 -0800513 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
hbosc82f2e12016-09-05 01:36:50 -0700514 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
515}
516
517TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
Steve Anton5b387312018-02-02 16:00:20 -0800518 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
519 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
520 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
521 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700522 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
523 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
524 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
Steve Anton5b387312018-02-02 16:00:20 -0800525
hbosc82f2e12016-09-05 01:36:50 -0700526 EXPECT_EQ(a.get(), b.get());
527 EXPECT_EQ(b.get(), c.get());
528}
529
530TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700531 // Caching should ensure |a| and |b| are the same report.
Steve Anton5b387312018-02-02 16:00:20 -0800532 rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
533 rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700534 EXPECT_EQ(a.get(), b.get());
535 // Invalidate cache by clearing it.
Steve Anton5b387312018-02-02 16:00:20 -0800536 stats_->stats_collector()->ClearCachedStatsReport();
537 rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700538 EXPECT_NE(b.get(), c.get());
539 // Invalidate cache by advancing time.
Steve Anton5b387312018-02-02 16:00:20 -0800540 fake_clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
541 rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700542 EXPECT_TRUE(d);
543 EXPECT_NE(c.get(), d.get());
544}
545
hbosc82f2e12016-09-05 01:36:50 -0700546TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
Steve Anton5b387312018-02-02 16:00:20 -0800547 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
548 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
549 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
hbosc82f2e12016-09-05 01:36:50 -0700550 // Cache is invalidated after 50 ms.
Steve Anton5b387312018-02-02 16:00:20 -0800551 fake_clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
552 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700553 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
554 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
555 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
556 EXPECT_EQ(a.get(), b.get());
557 // The act of doing |AdvanceTime| processes all messages. If this was not the
558 // case we might not require |c| to be fresher than |b|.
559 EXPECT_NE(c.get(), b.get());
560}
561
hbos6ab97ce2016-10-03 14:16:56 -0700562TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
Steve Anton5b387312018-02-02 16:00:20 -0800563 const char kTransportName[] = "transport";
564
565 pc_->AddVoiceChannel("audio", kTransportName);
566
hbos6ab97ce2016-10-03 14:16:56 -0700567 std::unique_ptr<CertificateInfo> local_certinfo =
568 CreateFakeCertificateAndInfoFromDers(
569 std::vector<std::string>({ "(local) single certificate" }));
Steve Anton5b387312018-02-02 16:00:20 -0800570 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
571
hbos6ab97ce2016-10-03 14:16:56 -0700572 std::unique_ptr<CertificateInfo> remote_certinfo =
573 CreateFakeCertificateAndInfoFromDers(
574 std::vector<std::string>({ "(remote) single certificate" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800575 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -0800576 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800577 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700578
Steve Anton5b387312018-02-02 16:00:20 -0800579 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ab97ce2016-10-03 14:16:56 -0700580
hbos23368e12016-12-21 04:29:17 -0800581 ExpectReportContainsCertificateInfo(report, *local_certinfo);
582 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700583}
584
hbos0adb8282016-11-23 02:32:06 -0800585TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
hbos0adb8282016-11-23 02:32:06 -0800586 // Audio
587 cricket::VoiceMediaInfo voice_media_info;
588
589 RtpCodecParameters inbound_audio_codec;
590 inbound_audio_codec.payload_type = 1;
deadbeefe702b302017-02-04 12:09:01 -0800591 inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
592 inbound_audio_codec.name = "opus";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100593 inbound_audio_codec.clock_rate = 1337;
hbos0adb8282016-11-23 02:32:06 -0800594 voice_media_info.receive_codecs.insert(
595 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
596
597 RtpCodecParameters outbound_audio_codec;
598 outbound_audio_codec.payload_type = 2;
deadbeefe702b302017-02-04 12:09:01 -0800599 outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
600 outbound_audio_codec.name = "isac";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100601 outbound_audio_codec.clock_rate = 1338;
hbos0adb8282016-11-23 02:32:06 -0800602 voice_media_info.send_codecs.insert(
603 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
604
Steve Anton57858b32018-02-15 15:19:50 -0800605 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800606 voice_media_channel->SetStats(voice_media_info);
hbos0adb8282016-11-23 02:32:06 -0800607
608 // Video
609 cricket::VideoMediaInfo video_media_info;
610
611 RtpCodecParameters inbound_video_codec;
612 inbound_video_codec.payload_type = 3;
deadbeefe702b302017-02-04 12:09:01 -0800613 inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
614 inbound_video_codec.name = "H264";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100615 inbound_video_codec.clock_rate = 1339;
hbos0adb8282016-11-23 02:32:06 -0800616 video_media_info.receive_codecs.insert(
617 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
618
619 RtpCodecParameters outbound_video_codec;
620 outbound_video_codec.payload_type = 4;
deadbeefe702b302017-02-04 12:09:01 -0800621 outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
622 outbound_video_codec.name = "VP8";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100623 outbound_video_codec.clock_rate = 1340;
hbos0adb8282016-11-23 02:32:06 -0800624 video_media_info.send_codecs.insert(
625 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
626
Steve Anton57858b32018-02-15 15:19:50 -0800627 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800628 video_media_channel->SetStats(video_media_info);
hbos0adb8282016-11-23 02:32:06 -0800629
Steve Anton5b387312018-02-02 16:00:20 -0800630 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0adb8282016-11-23 02:32:06 -0800631
Steve Anton57858b32018-02-15 15:19:50 -0800632 RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1",
633 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800634 expected_inbound_audio_codec.payload_type = 1;
hbos13f54b22017-02-28 06:56:04 -0800635 expected_inbound_audio_codec.mime_type = "audio/opus";
hbos0adb8282016-11-23 02:32:06 -0800636 expected_inbound_audio_codec.clock_rate = 1337;
637
Steve Anton57858b32018-02-15 15:19:50 -0800638 RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
639 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800640 expected_outbound_audio_codec.payload_type = 2;
hbos13f54b22017-02-28 06:56:04 -0800641 expected_outbound_audio_codec.mime_type = "audio/isac";
hbos0adb8282016-11-23 02:32:06 -0800642 expected_outbound_audio_codec.clock_rate = 1338;
643
Steve Anton57858b32018-02-15 15:19:50 -0800644 RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
645 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800646 expected_inbound_video_codec.payload_type = 3;
hbos13f54b22017-02-28 06:56:04 -0800647 expected_inbound_video_codec.mime_type = "video/H264";
hbos0adb8282016-11-23 02:32:06 -0800648 expected_inbound_video_codec.clock_rate = 1339;
649
Steve Anton57858b32018-02-15 15:19:50 -0800650 RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
651 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800652 expected_outbound_video_codec.payload_type = 4;
hbos13f54b22017-02-28 06:56:04 -0800653 expected_outbound_video_codec.mime_type = "video/VP8";
hbos0adb8282016-11-23 02:32:06 -0800654 expected_outbound_video_codec.clock_rate = 1340;
655
nissec8ee8822017-01-18 07:20:55 -0800656 ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800657 EXPECT_EQ(expected_inbound_audio_codec,
658 report->Get(expected_inbound_audio_codec.id())->cast_to<
659 RTCCodecStats>());
660
nissec8ee8822017-01-18 07:20:55 -0800661 ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800662 EXPECT_EQ(expected_outbound_audio_codec,
663 report->Get(expected_outbound_audio_codec.id())->cast_to<
664 RTCCodecStats>());
665
nissec8ee8822017-01-18 07:20:55 -0800666 ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800667 EXPECT_EQ(expected_inbound_video_codec,
668 report->Get(expected_inbound_video_codec.id())->cast_to<
669 RTCCodecStats>());
670
nissec8ee8822017-01-18 07:20:55 -0800671 ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800672 EXPECT_EQ(expected_outbound_video_codec,
673 report->Get(expected_outbound_video_codec.id())->cast_to<
674 RTCCodecStats>());
675}
676
hbos6ab97ce2016-10-03 14:16:56 -0700677TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
Steve Anton5b387312018-02-02 16:00:20 -0800678 const char kAudioTransport[] = "audio";
679 const char kVideoTransport[] = "video";
680
681 pc_->AddVoiceChannel("audio", kAudioTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700682 std::unique_ptr<CertificateInfo> audio_local_certinfo =
683 CreateFakeCertificateAndInfoFromDers(
684 std::vector<std::string>({ "(local) audio" }));
Steve Anton5b387312018-02-02 16:00:20 -0800685 pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700686 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
687 CreateFakeCertificateAndInfoFromDers(
688 std::vector<std::string>({ "(remote) audio" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800689 pc_->SetRemoteCertChain(
690 kAudioTransport,
691 audio_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700692
Steve Anton5b387312018-02-02 16:00:20 -0800693 pc_->AddVideoChannel("video", kVideoTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700694 std::unique_ptr<CertificateInfo> video_local_certinfo =
695 CreateFakeCertificateAndInfoFromDers(
696 std::vector<std::string>({ "(local) video" }));
Steve Anton5b387312018-02-02 16:00:20 -0800697 pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700698 std::unique_ptr<CertificateInfo> video_remote_certinfo =
699 CreateFakeCertificateAndInfoFromDers(
700 std::vector<std::string>({ "(remote) video" }));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800701 pc_->SetRemoteCertChain(
702 kVideoTransport,
703 video_remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700704
Steve Anton5b387312018-02-02 16:00:20 -0800705 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800706 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
707 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
708 ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
709 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700710}
711
712TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
Steve Anton5b387312018-02-02 16:00:20 -0800713 const char kTransportName[] = "transport";
714
715 pc_->AddVoiceChannel("audio", kTransportName);
716
hbos6ab97ce2016-10-03 14:16:56 -0700717 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800718 CreateFakeCertificateAndInfoFromDers(
719 {"(local) this", "(local) is", "(local) a", "(local) chain"});
720 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
721
hbos6ab97ce2016-10-03 14:16:56 -0700722 std::unique_ptr<CertificateInfo> remote_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800723 CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
724 "(remote) another",
725 "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800726 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -0800727 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800728 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos6ab97ce2016-10-03 14:16:56 -0700729
Steve Anton5b387312018-02-02 16:00:20 -0800730 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800731 ExpectReportContainsCertificateInfo(report, *local_certinfo);
732 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700733}
734
hboscc555c52016-10-18 12:48:31 -0700735TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
Steve Anton5b387312018-02-02 16:00:20 -0800736 pc_->AddSctpDataChannel(new MockDataChannel(0, "MockDataChannel0",
737 DataChannelInterface::kConnecting,
738 "udp", 1, 2, 3, 4));
hbosdbb64d82016-12-21 01:57:46 -0800739 RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0);
740 expected_data_channel0.label = "MockDataChannel0";
741 expected_data_channel0.protocol = "udp";
742 expected_data_channel0.datachannelid = 0;
743 expected_data_channel0.state = "connecting";
744 expected_data_channel0.messages_sent = 1;
745 expected_data_channel0.bytes_sent = 2;
746 expected_data_channel0.messages_received = 3;
747 expected_data_channel0.bytes_received = 4;
748
Steve Anton5b387312018-02-02 16:00:20 -0800749 pc_->AddSctpDataChannel(new MockDataChannel(
Steve Antonbe5e2082018-01-24 15:29:17 -0800750 1, "MockDataChannel1", DataChannelInterface::kOpen, "tcp", 5, 6, 7, 8));
hbosdbb64d82016-12-21 01:57:46 -0800751 RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0);
752 expected_data_channel1.label = "MockDataChannel1";
753 expected_data_channel1.protocol = "tcp";
754 expected_data_channel1.datachannelid = 1;
755 expected_data_channel1.state = "open";
756 expected_data_channel1.messages_sent = 5;
757 expected_data_channel1.bytes_sent = 6;
758 expected_data_channel1.messages_received = 7;
759 expected_data_channel1.bytes_received = 8;
760
Steve Anton5b387312018-02-02 16:00:20 -0800761 pc_->AddSctpDataChannel(new MockDataChannel(2, "MockDataChannel2",
762 DataChannelInterface::kClosing,
763 "udp", 9, 10, 11, 12));
hbosdbb64d82016-12-21 01:57:46 -0800764 RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0);
765 expected_data_channel2.label = "MockDataChannel2";
766 expected_data_channel2.protocol = "udp";
767 expected_data_channel2.datachannelid = 2;
768 expected_data_channel2.state = "closing";
769 expected_data_channel2.messages_sent = 9;
770 expected_data_channel2.bytes_sent = 10;
771 expected_data_channel2.messages_received = 11;
772 expected_data_channel2.bytes_received = 12;
773
Steve Anton5b387312018-02-02 16:00:20 -0800774 pc_->AddSctpDataChannel(new MockDataChannel(3, "MockDataChannel3",
775 DataChannelInterface::kClosed,
776 "tcp", 13, 14, 15, 16));
hbosdbb64d82016-12-21 01:57:46 -0800777 RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0);
778 expected_data_channel3.label = "MockDataChannel3";
779 expected_data_channel3.protocol = "tcp";
780 expected_data_channel3.datachannelid = 3;
781 expected_data_channel3.state = "closed";
782 expected_data_channel3.messages_sent = 13;
783 expected_data_channel3.bytes_sent = 14;
784 expected_data_channel3.messages_received = 15;
785 expected_data_channel3.bytes_received = 16;
hboscc555c52016-10-18 12:48:31 -0700786
Steve Anton5b387312018-02-02 16:00:20 -0800787 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
788
hbosdbb64d82016-12-21 01:57:46 -0800789 ASSERT_TRUE(report->Get(expected_data_channel0.id()));
790 EXPECT_EQ(expected_data_channel0,
791 report->Get(expected_data_channel0.id())->cast_to<
792 RTCDataChannelStats>());
793 ASSERT_TRUE(report->Get(expected_data_channel1.id()));
794 EXPECT_EQ(expected_data_channel1,
795 report->Get(expected_data_channel1.id())->cast_to<
796 RTCDataChannelStats>());
797 ASSERT_TRUE(report->Get(expected_data_channel2.id()));
798 EXPECT_EQ(expected_data_channel2,
799 report->Get(expected_data_channel2.id())->cast_to<
800 RTCDataChannelStats>());
801 ASSERT_TRUE(report->Get(expected_data_channel3.id()));
802 EXPECT_EQ(expected_data_channel3,
803 report->Get(expected_data_channel3.id())->cast_to<
804 RTCDataChannelStats>());
hboscc555c52016-10-18 12:48:31 -0700805}
806
hbosab9f6e42016-10-07 02:18:47 -0700807TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
808 // Candidates in the first transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -0800809 std::unique_ptr<cricket::Candidate> a_local_host =
810 CreateFakeCandidate("1.2.3.4", 5, "a_local_host's protocol",
811 rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0);
hbosc42ba322016-12-21 03:31:45 -0800812 RTCLocalIceCandidateStats expected_a_local_host(
813 "RTCIceCandidate_" + a_local_host->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800814 expected_a_local_host.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -0800815 expected_a_local_host.network_type = "vpn";
hbosc42ba322016-12-21 03:31:45 -0800816 expected_a_local_host.ip = "1.2.3.4";
817 expected_a_local_host.port = 5;
818 expected_a_local_host.protocol = "a_local_host's protocol";
819 expected_a_local_host.candidate_type = "host";
820 expected_a_local_host.priority = 0;
hbosc3a2b7f2017-01-02 04:46:15 -0800821 EXPECT_FALSE(*expected_a_local_host.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800822
hbosab9f6e42016-10-07 02:18:47 -0700823 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800824 "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
825 cricket::STUN_PORT_TYPE, 1);
hbosc42ba322016-12-21 03:31:45 -0800826 RTCRemoteIceCandidateStats expected_a_remote_srflx(
827 "RTCIceCandidate_" + a_remote_srflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800828 expected_a_remote_srflx.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -0800829 expected_a_remote_srflx.ip = "6.7.8.9";
830 expected_a_remote_srflx.port = 10;
831 expected_a_remote_srflx.protocol = "remote_srflx's protocol";
832 expected_a_remote_srflx.candidate_type = "srflx";
833 expected_a_remote_srflx.priority = 1;
hbosd17a5a72017-01-02 08:09:59 -0800834 expected_a_remote_srflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800835 EXPECT_TRUE(*expected_a_remote_srflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800836
hbosab9f6e42016-10-07 02:18:47 -0700837 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800838 "11.12.13.14", 15, "a_local_prflx's protocol", rtc::ADAPTER_TYPE_CELLULAR,
839 cricket::PRFLX_PORT_TYPE, 2);
hbosc42ba322016-12-21 03:31:45 -0800840 RTCLocalIceCandidateStats expected_a_local_prflx(
841 "RTCIceCandidate_" + a_local_prflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800842 expected_a_local_prflx.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -0800843 expected_a_local_prflx.network_type = "cellular";
hbosc42ba322016-12-21 03:31:45 -0800844 expected_a_local_prflx.ip = "11.12.13.14";
845 expected_a_local_prflx.port = 15;
846 expected_a_local_prflx.protocol = "a_local_prflx's protocol";
847 expected_a_local_prflx.candidate_type = "prflx";
848 expected_a_local_prflx.priority = 2;
hbosd17a5a72017-01-02 08:09:59 -0800849 expected_a_local_prflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800850 EXPECT_FALSE(*expected_a_local_prflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800851
hbosab9f6e42016-10-07 02:18:47 -0700852 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800853 "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
854 cricket::RELAY_PORT_TYPE, 3);
hbosc42ba322016-12-21 03:31:45 -0800855 RTCRemoteIceCandidateStats expected_a_remote_relay(
856 "RTCIceCandidate_" + a_remote_relay->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800857 expected_a_remote_relay.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -0800858 expected_a_remote_relay.ip = "16.17.18.19";
859 expected_a_remote_relay.port = 20;
860 expected_a_remote_relay.protocol = "a_remote_relay's protocol";
861 expected_a_remote_relay.candidate_type = "relay";
862 expected_a_remote_relay.priority = 3;
hbosd17a5a72017-01-02 08:09:59 -0800863 expected_a_remote_relay.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800864 EXPECT_TRUE(*expected_a_remote_relay.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800865
hbosab9f6e42016-10-07 02:18:47 -0700866 // Candidates in the second transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -0800867 std::unique_ptr<cricket::Candidate> b_local =
868 CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
869 rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 03:31:45 -0800870 RTCLocalIceCandidateStats expected_b_local(
871 "RTCIceCandidate_" + b_local->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800872 expected_b_local.transport_id = "RTCTransport_b_0";
Gary Liu37e489c2017-11-21 10:49:36 -0800873 expected_b_local.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -0800874 expected_b_local.ip = "42.42.42.42";
875 expected_b_local.port = 42;
876 expected_b_local.protocol = "b_local's protocol";
877 expected_b_local.candidate_type = "host";
878 expected_b_local.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -0800879 expected_b_local.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800880 EXPECT_FALSE(*expected_b_local.is_remote);
hbosc42ba322016-12-21 03:31:45 -0800881
hbosab9f6e42016-10-07 02:18:47 -0700882 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800883 "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
884 cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 03:31:45 -0800885 RTCRemoteIceCandidateStats expected_b_remote(
886 "RTCIceCandidate_" + b_remote->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -0800887 expected_b_remote.transport_id = "RTCTransport_b_0";
hbosc42ba322016-12-21 03:31:45 -0800888 expected_b_remote.ip = "42.42.42.42";
889 expected_b_remote.port = 42;
890 expected_b_remote.protocol = "b_remote's protocol";
891 expected_b_remote.candidate_type = "host";
892 expected_b_remote.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -0800893 expected_b_remote.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -0800894 EXPECT_TRUE(*expected_b_remote.is_remote);
hbosab9f6e42016-10-07 02:18:47 -0700895
hbosab9f6e42016-10-07 02:18:47 -0700896 cricket::TransportChannelStats a_transport_channel_stats;
897 a_transport_channel_stats.connection_infos.push_back(
898 cricket::ConnectionInfo());
899 a_transport_channel_stats.connection_infos[0].local_candidate =
900 *a_local_host.get();
901 a_transport_channel_stats.connection_infos[0].remote_candidate =
902 *a_remote_srflx.get();
903 a_transport_channel_stats.connection_infos.push_back(
904 cricket::ConnectionInfo());
905 a_transport_channel_stats.connection_infos[1].local_candidate =
906 *a_local_prflx.get();
907 a_transport_channel_stats.connection_infos[1].remote_candidate =
908 *a_remote_relay.get();
Steve Anton5b387312018-02-02 16:00:20 -0800909
910 pc_->AddVoiceChannel("audio", "a");
911 pc_->SetTransportStats("a", a_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -0700912
913 cricket::TransportChannelStats b_transport_channel_stats;
914 b_transport_channel_stats.connection_infos.push_back(
915 cricket::ConnectionInfo());
916 b_transport_channel_stats.connection_infos[0].local_candidate =
917 *b_local.get();
918 b_transport_channel_stats.connection_infos[0].remote_candidate =
919 *b_remote.get();
hbosab9f6e42016-10-07 02:18:47 -0700920
Steve Anton5b387312018-02-02 16:00:20 -0800921 pc_->AddVideoChannel("video", "b");
922 pc_->SetTransportStats("b", b_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -0700923
Steve Anton5b387312018-02-02 16:00:20 -0800924 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbosc42ba322016-12-21 03:31:45 -0800925
hbosb4e426e2017-01-02 09:59:31 -0800926 ASSERT_TRUE(report->Get(expected_a_local_host.id()));
hbosc42ba322016-12-21 03:31:45 -0800927 EXPECT_EQ(expected_a_local_host,
928 report->Get(expected_a_local_host.id())->cast_to<
929 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800930 ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
hbosc42ba322016-12-21 03:31:45 -0800931 EXPECT_EQ(expected_a_remote_srflx,
932 report->Get(expected_a_remote_srflx.id())->cast_to<
933 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800934 ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
hbosc42ba322016-12-21 03:31:45 -0800935 EXPECT_EQ(expected_a_local_prflx,
936 report->Get(expected_a_local_prflx.id())->cast_to<
937 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800938 ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
hbosc42ba322016-12-21 03:31:45 -0800939 EXPECT_EQ(expected_a_remote_relay,
940 report->Get(expected_a_remote_relay.id())->cast_to<
941 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800942 ASSERT_TRUE(report->Get(expected_b_local.id()));
hbosc42ba322016-12-21 03:31:45 -0800943 EXPECT_EQ(expected_b_local,
944 report->Get(expected_b_local.id())->cast_to<
945 RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800946 ASSERT_TRUE(report->Get(expected_b_remote.id()));
hbosc42ba322016-12-21 03:31:45 -0800947 EXPECT_EQ(expected_b_remote,
948 report->Get(expected_b_remote.id())->cast_to<
949 RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -0800950 EXPECT_TRUE(report->Get("RTCTransport_a_0"));
951 EXPECT_TRUE(report->Get("RTCTransport_b_0"));
hbosab9f6e42016-10-07 02:18:47 -0700952}
953
hbosc47a0c32016-10-11 14:54:49 -0700954TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
Steve Anton5b387312018-02-02 16:00:20 -0800955 const char kTransportName[] = "transport";
hbos338f78a2017-02-07 06:41:21 -0800956
Gary Liu37e489c2017-11-21 10:49:36 -0800957 std::unique_ptr<cricket::Candidate> local_candidate =
958 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
959 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -0700960 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -0800961 "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
962 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -0700963
hbosc47a0c32016-10-11 14:54:49 -0700964 cricket::ConnectionInfo connection_info;
hbos338f78a2017-02-07 06:41:21 -0800965 connection_info.best_connection = false;
hbosc47a0c32016-10-11 14:54:49 -0700966 connection_info.local_candidate = *local_candidate.get();
967 connection_info.remote_candidate = *remote_candidate.get();
968 connection_info.writable = true;
969 connection_info.sent_total_bytes = 42;
970 connection_info.recv_total_bytes = 1234;
hbosbf8d3e52017-02-28 06:34:47 -0800971 connection_info.total_round_trip_time_ms = 0;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100972 connection_info.current_round_trip_time_ms = rtc::nullopt;
hbosd82f5122016-12-09 04:12:39 -0800973 connection_info.recv_ping_requests = 2020;
hbose448dd52016-12-12 01:22:53 -0800974 connection_info.sent_ping_requests_total = 2020;
975 connection_info.sent_ping_requests_before_first_response = 2000;
hbosc47a0c32016-10-11 14:54:49 -0700976 connection_info.recv_ping_responses = 4321;
977 connection_info.sent_ping_responses = 1000;
hbos06495bc2017-01-02 08:08:18 -0800978 connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
979 connection_info.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -0800980 connection_info.nominated = false;
hbosc47a0c32016-10-11 14:54:49 -0700981
982 cricket::TransportChannelStats transport_channel_stats;
hbos0583b282016-11-30 01:50:14 -0800983 transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
hbosc47a0c32016-10-11 14:54:49 -0700984 transport_channel_stats.connection_infos.push_back(connection_info);
hbosc47a0c32016-10-11 14:54:49 -0700985
Steve Anton5b387312018-02-02 16:00:20 -0800986 pc_->AddVideoChannel("video", kTransportName);
987 pc_->SetTransportStats(kTransportName, transport_channel_stats);
hbosc47a0c32016-10-11 14:54:49 -0700988
Steve Anton5b387312018-02-02 16:00:20 -0800989 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -0800990
991 RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" +
992 local_candidate->id() + "_" +
993 remote_candidate->id(),
994 report->timestamp_us());
995 expected_pair.transport_id =
996 "RTCTransport_transport_" +
997 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
998 expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
999 expected_pair.remote_candidate_id =
1000 "RTCIceCandidate_" + remote_candidate->id();
hbos06495bc2017-01-02 08:08:18 -08001001 expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1002 expected_pair.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -08001003 expected_pair.nominated = false;
hbos0583b282016-11-30 01:50:14 -08001004 expected_pair.writable = true;
1005 expected_pair.bytes_sent = 42;
1006 expected_pair.bytes_received = 1234;
hbosbf8d3e52017-02-28 06:34:47 -08001007 expected_pair.total_round_trip_time = 0.0;
hbosd82f5122016-12-09 04:12:39 -08001008 expected_pair.requests_received = 2020;
hbose448dd52016-12-12 01:22:53 -08001009 expected_pair.requests_sent = 2000;
hbos0583b282016-11-30 01:50:14 -08001010 expected_pair.responses_received = 4321;
1011 expected_pair.responses_sent = 1000;
hbose448dd52016-12-12 01:22:53 -08001012 expected_pair.consent_requests_sent = (2020 - 2000);
hbosbf8d3e52017-02-28 06:34:47 -08001013 // |expected_pair.current_round_trip_time| should be undefined because the
1014 // current RTT is not set.
hbos338f78a2017-02-07 06:41:21 -08001015 // |expected_pair.available_[outgoing/incoming]_bitrate| should be undefined
1016 // because is is not the current pair.
hbos0583b282016-11-30 01:50:14 -08001017
hbosdbb64d82016-12-21 01:57:46 -08001018 ASSERT_TRUE(report->Get(expected_pair.id()));
hbos0583b282016-11-30 01:50:14 -08001019 EXPECT_EQ(
1020 expected_pair,
1021 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
hbosb4e426e2017-01-02 09:59:31 -08001022 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
hbos0583b282016-11-30 01:50:14 -08001023
hbos92eaec62017-02-27 01:38:08 -08001024 // Set nominated and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001025 transport_channel_stats.connection_infos[0].nominated = true;
1026 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1027 report = stats_->GetFreshStatsReport();
hbos92eaec62017-02-27 01:38:08 -08001028 expected_pair.nominated = true;
1029 ASSERT_TRUE(report->Get(expected_pair.id()));
1030 EXPECT_EQ(
1031 expected_pair,
1032 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1033 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1034
hbosbf8d3e52017-02-28 06:34:47 -08001035 // Set round trip times and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001036 transport_channel_stats.connection_infos[0].total_round_trip_time_ms = 7331;
1037 transport_channel_stats.connection_infos[0].current_round_trip_time_ms = 1337;
1038 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1039 report = stats_->GetFreshStatsReport();
hbosbf8d3e52017-02-28 06:34:47 -08001040 expected_pair.total_round_trip_time = 7.331;
1041 expected_pair.current_round_trip_time = 1.337;
1042 ASSERT_TRUE(report->Get(expected_pair.id()));
1043 EXPECT_EQ(
1044 expected_pair,
1045 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1046 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1047
hbos338f78a2017-02-07 06:41:21 -08001048 // Make pair the current pair, clear bandwidth and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001049 transport_channel_stats.connection_infos[0].best_connection = true;
1050 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1051 report = stats_->GetFreshStatsReport();
hbos338f78a2017-02-07 06:41:21 -08001052 // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
1053 // undefined because bandwidth is not set.
1054 ASSERT_TRUE(report->Get(expected_pair.id()));
1055 EXPECT_EQ(
1056 expected_pair,
1057 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1058 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1059
1060 // Set bandwidth and "GetStats" again.
stefanf79ade12017-06-02 06:44:03 -07001061 webrtc::Call::Stats call_stats;
1062 const int kSendBandwidth = 888;
1063 call_stats.send_bandwidth_bps = kSendBandwidth;
1064 const int kRecvBandwidth = 999;
1065 call_stats.recv_bandwidth_bps = kRecvBandwidth;
Steve Anton5b387312018-02-02 16:00:20 -08001066 pc_->SetCallStats(call_stats);
1067 report = stats_->GetFreshStatsReport();
stefanf79ade12017-06-02 06:44:03 -07001068 expected_pair.available_outgoing_bitrate = kSendBandwidth;
1069 expected_pair.available_incoming_bitrate = kRecvBandwidth;
hbos338f78a2017-02-07 06:41:21 -08001070 ASSERT_TRUE(report->Get(expected_pair.id()));
1071 EXPECT_EQ(
1072 expected_pair,
1073 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1074 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1075
hbosc42ba322016-12-21 03:31:45 -08001076 RTCLocalIceCandidateStats expected_local_candidate(
1077 *expected_pair.local_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001078 expected_local_candidate.transport_id = *expected_pair.transport_id;
Gary Liu37e489c2017-11-21 10:49:36 -08001079 expected_local_candidate.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -08001080 expected_local_candidate.ip = "42.42.42.42";
1081 expected_local_candidate.port = 42;
1082 expected_local_candidate.protocol = "protocol";
1083 expected_local_candidate.candidate_type = "host";
1084 expected_local_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001085 expected_local_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001086 EXPECT_FALSE(*expected_local_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001087 ASSERT_TRUE(report->Get(expected_local_candidate.id()));
1088 EXPECT_EQ(expected_local_candidate,
1089 report->Get(expected_local_candidate.id())->cast_to<
1090 RTCLocalIceCandidateStats>());
1091
1092 RTCRemoteIceCandidateStats expected_remote_candidate(
1093 *expected_pair.remote_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001094 expected_remote_candidate.transport_id = *expected_pair.transport_id;
hbosc42ba322016-12-21 03:31:45 -08001095 expected_remote_candidate.ip = "42.42.42.42";
1096 expected_remote_candidate.port = 42;
1097 expected_remote_candidate.protocol = "protocol";
1098 expected_remote_candidate.candidate_type = "host";
1099 expected_remote_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001100 expected_remote_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001101 EXPECT_TRUE(*expected_remote_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001102 ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
1103 EXPECT_EQ(expected_remote_candidate,
1104 report->Get(expected_remote_candidate.id())->cast_to<
1105 RTCRemoteIceCandidateStats>());
hbosc47a0c32016-10-11 14:54:49 -07001106}
1107
hbosd565b732016-08-30 14:04:35 -07001108TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosd565b732016-08-30 14:04:35 -07001109 {
Steve Anton5b387312018-02-02 16:00:20 -08001110 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001111 RTCPeerConnectionStats expected("RTCPeerConnection",
1112 report->timestamp_us());
1113 expected.data_channels_opened = 0;
1114 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001115 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001116 EXPECT_EQ(expected,
1117 report->Get("RTCPeerConnection")->cast_to<
1118 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001119 }
1120
hbos82ebe022016-11-14 01:41:09 -08001121 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create(
1122 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001123 pc_->SignalDataChannelCreated()(dummy_channel_a.get());
hbos82ebe022016-11-14 01:41:09 -08001124 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create(
1125 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001126 pc_->SignalDataChannelCreated()(dummy_channel_b.get());
hbosd565b732016-08-30 14:04:35 -07001127
hbos82ebe022016-11-14 01:41:09 -08001128 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1129 // Closing a channel that is not opened should not affect the counts.
1130 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1131
hbosd565b732016-08-30 14:04:35 -07001132 {
Steve Anton5b387312018-02-02 16:00:20 -08001133 rtc::scoped_refptr<const RTCStatsReport> report =
1134 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001135 RTCPeerConnectionStats expected("RTCPeerConnection",
1136 report->timestamp_us());
1137 expected.data_channels_opened = 1;
1138 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001139 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001140 EXPECT_EQ(expected,
1141 report->Get("RTCPeerConnection")->cast_to<
1142 RTCPeerConnectionStats>());
1143 }
1144
1145 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1146 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1147
1148 {
Steve Anton5b387312018-02-02 16:00:20 -08001149 rtc::scoped_refptr<const RTCStatsReport> report =
1150 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001151 RTCPeerConnectionStats expected("RTCPeerConnection",
1152 report->timestamp_us());
1153 expected.data_channels_opened = 2;
1154 expected.data_channels_closed = 1;
hbosdbb64d82016-12-21 01:57:46 -08001155 ASSERT_TRUE(report->Get("RTCPeerConnection"));
hbos82ebe022016-11-14 01:41:09 -08001156 EXPECT_EQ(expected,
1157 report->Get("RTCPeerConnection")->cast_to<
1158 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001159 }
hbos5bf9def2017-03-20 03:14:14 -07001160
1161 // Re-opening a data channel (or opening a new data channel that is re-using
1162 // the same address in memory) should increase the opened count.
1163 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1164
1165 {
Steve Anton5b387312018-02-02 16:00:20 -08001166 rtc::scoped_refptr<const RTCStatsReport> report =
1167 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001168 RTCPeerConnectionStats expected("RTCPeerConnection",
1169 report->timestamp_us());
1170 expected.data_channels_opened = 3;
1171 expected.data_channels_closed = 1;
1172 ASSERT_TRUE(report->Get("RTCPeerConnection"));
1173 EXPECT_EQ(expected,
1174 report->Get("RTCPeerConnection")->cast_to<
1175 RTCPeerConnectionStats>());
1176 }
1177
1178 dummy_channel_a->SignalClosed(dummy_channel_a.get());
1179 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1180
1181 {
Steve Anton5b387312018-02-02 16:00:20 -08001182 rtc::scoped_refptr<const RTCStatsReport> report =
1183 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001184 RTCPeerConnectionStats expected("RTCPeerConnection",
1185 report->timestamp_us());
1186 expected.data_channels_opened = 3;
1187 expected.data_channels_closed = 3;
1188 ASSERT_TRUE(report->Get("RTCPeerConnection"));
1189 EXPECT_EQ(expected,
1190 report->Get("RTCPeerConnection")->cast_to<
1191 RTCPeerConnectionStats>());
1192 }
hbosd565b732016-08-30 14:04:35 -07001193}
1194
hbos09bc1282016-11-08 06:29:22 -08001195TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001196 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
hbos09bc1282016-11-08 06:29:22 -08001197 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001198 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001199 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001200
1201 // Local audio track
hbos9e302742017-01-20 02:47:10 -08001202 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
1203 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
1204 MediaStreamTrackInterface::kEnded);
1205 local_stream->AddTrack(static_cast<AudioTrackInterface*>(
1206 local_audio_track.get()));
1207
1208 cricket::VoiceSenderInfo voice_sender_info_ssrc1;
1209 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1210 voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
1211 voice_sender_info_ssrc1.audio_level = 32767;
zsteine76bd3a2017-07-14 12:17:49 -07001212 voice_sender_info_ssrc1.total_input_energy = 0.25;
1213 voice_sender_info_ssrc1.total_input_duration = 0.5;
Ivo Creusen56d46092017-11-24 17:29:59 +01001214 voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
1215 voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
hbos9e302742017-01-20 02:47:10 -08001216
Steve Anton5b387312018-02-02 16:00:20 -08001217 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001218 {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001219 {}, {}, {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001220
Steve Anton5b387312018-02-02 16:00:20 -08001221 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001222
1223 RTCMediaStreamStats expected_local_stream(
1224 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001225 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001226 expected_local_stream.track_ids = {
1227 IdForType<RTCMediaStreamTrackStats>(report)};
1228 ASSERT_TRUE(report->Get(expected_local_stream.id()))
1229 << "Did not find " << expected_local_stream.id() << " in "
1230 << report->ToJson();
1231 EXPECT_EQ(
1232 expected_local_stream,
1233 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1234
1235 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
1236 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1237 RTCMediaStreamTrackKind::kAudio);
1238 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
1239 expected_local_audio_track_ssrc1.remote_source = false;
1240 expected_local_audio_track_ssrc1.ended = true;
1241 expected_local_audio_track_ssrc1.detached = false;
1242 expected_local_audio_track_ssrc1.audio_level = 1.0;
1243 expected_local_audio_track_ssrc1.total_audio_energy = 0.25;
1244 expected_local_audio_track_ssrc1.total_samples_duration = 0.5;
1245 expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
1246 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
1247 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
1248 << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
1249 << report->ToJson();
1250 EXPECT_EQ(expected_local_audio_track_ssrc1,
1251 report->Get(expected_local_audio_track_ssrc1.id())
1252 ->cast_to<RTCMediaStreamTrackStats>());
1253}
1254
1255TEST_F(RTCStatsCollectorTest,
1256 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001257 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001258 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001259 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001260
hbos09bc1282016-11-08 06:29:22 -08001261 // Remote audio track
hbos9e302742017-01-20 02:47:10 -08001262 rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
1263 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
1264 MediaStreamTrackInterface::kLive);
1265 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(
1266 remote_audio_track.get()));
1267
1268 cricket::VoiceReceiverInfo voice_receiver_info;
1269 voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
1270 voice_receiver_info.local_stats[0].ssrc = 3;
1271 voice_receiver_info.audio_level = 16383;
zsteine76bd3a2017-07-14 12:17:49 -07001272 voice_receiver_info.total_output_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001273 voice_receiver_info.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001274 voice_receiver_info.total_output_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001275 voice_receiver_info.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001276 voice_receiver_info.concealment_events = 12;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001277 voice_receiver_info.jitter_buffer_delay_seconds = 3456;
hbos9e302742017-01-20 02:47:10 -08001278
Steve Anton5b387312018-02-02 16:00:20 -08001279 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001280 {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
1281 {}, {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001282
Steve Anton5b387312018-02-02 16:00:20 -08001283 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001284
hbos09bc1282016-11-08 06:29:22 -08001285 RTCMediaStreamStats expected_remote_stream(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001286 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001287 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001288 expected_remote_stream.track_ids =
1289 std::vector<std::string>({IdForType<RTCMediaStreamTrackStats>(report)});
1290 ASSERT_TRUE(report->Get(expected_remote_stream.id()))
1291 << "Did not find " << expected_remote_stream.id() << " in "
1292 << report->ToJson();
hbos09bc1282016-11-08 06:29:22 -08001293 EXPECT_EQ(expected_remote_stream,
1294 report->Get(expected_remote_stream.id())->cast_to<
1295 RTCMediaStreamStats>());
1296
hbos09bc1282016-11-08 06:29:22 -08001297 RTCMediaStreamTrackStats expected_remote_audio_track(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001298 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1299 RTCMediaStreamTrackKind::kAudio);
hbos09bc1282016-11-08 06:29:22 -08001300 expected_remote_audio_track.track_identifier = remote_audio_track->id();
1301 expected_remote_audio_track.remote_source = true;
1302 expected_remote_audio_track.ended = false;
1303 expected_remote_audio_track.detached = false;
hbos9e302742017-01-20 02:47:10 -08001304 expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
zsteine76bd3a2017-07-14 12:17:49 -07001305 expected_remote_audio_track.total_audio_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001306 expected_remote_audio_track.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001307 expected_remote_audio_track.total_samples_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001308 expected_remote_audio_track.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001309 expected_remote_audio_track.concealment_events = 12;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001310 expected_remote_audio_track.jitter_buffer_delay = 3456;
hbosdbb64d82016-12-21 01:57:46 -08001311 ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
hbos09bc1282016-11-08 06:29:22 -08001312 EXPECT_EQ(expected_remote_audio_track,
1313 report->Get(expected_remote_audio_track.id())->cast_to<
1314 RTCMediaStreamTrackStats>());
1315}
1316
1317TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001318 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
hbos09bc1282016-11-08 06:29:22 -08001319 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001320 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001321 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001322
1323 // Local video track
hbos9e302742017-01-20 02:47:10 -08001324 rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
1325 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
1326 MediaStreamTrackInterface::kLive);
1327 local_stream->AddTrack(static_cast<VideoTrackInterface*>(
1328 local_video_track.get()));
hbos09bc1282016-11-08 06:29:22 -08001329
hbos9e302742017-01-20 02:47:10 -08001330 cricket::VideoSenderInfo video_sender_info_ssrc1;
1331 video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1332 video_sender_info_ssrc1.local_stats[0].ssrc = 1;
1333 video_sender_info_ssrc1.send_frame_width = 1234;
1334 video_sender_info_ssrc1.send_frame_height = 4321;
hbosfefe0762017-01-20 06:14:25 -08001335 video_sender_info_ssrc1.frames_encoded = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001336 video_sender_info_ssrc1.huge_frames_sent = 1;
hbos9e302742017-01-20 02:47:10 -08001337
Steve Anton5b387312018-02-02 16:00:20 -08001338 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001339 {}, {},
1340 {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001341 {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001342
Steve Anton5b387312018-02-02 16:00:20 -08001343 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001344
1345 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1346 ASSERT_EQ(1, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1347 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1348 ASSERT_EQ(1, stats_of_track_type.size())
1349 << "Wrong number of tracks in " << report->ToJson();
1350
1351 RTCMediaStreamStats expected_local_stream(stats_of_my_type[0]->id(),
1352 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001353 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001354 expected_local_stream.track_ids =
1355 std::vector<std::string>({stats_of_track_type[0]->id()});
1356 ASSERT_TRUE(report->Get(expected_local_stream.id()));
1357 EXPECT_EQ(
1358 expected_local_stream,
1359 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1360
1361 RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
1362 stats_of_track_type[0]->id(), report->timestamp_us(),
1363 RTCMediaStreamTrackKind::kVideo);
1364 expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
1365 expected_local_video_track_ssrc1.remote_source = false;
1366 expected_local_video_track_ssrc1.ended = false;
1367 expected_local_video_track_ssrc1.detached = false;
1368 expected_local_video_track_ssrc1.frame_width = 1234;
1369 expected_local_video_track_ssrc1.frame_height = 4321;
1370 expected_local_video_track_ssrc1.frames_sent = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001371 expected_local_video_track_ssrc1.huge_frames_sent = 1;
Harald Alvestranda3dab842018-01-14 09:18:58 +01001372 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
1373 EXPECT_EQ(expected_local_video_track_ssrc1,
1374 report->Get(expected_local_video_track_ssrc1.id())
1375 ->cast_to<RTCMediaStreamTrackStats>());
1376}
1377
1378TEST_F(RTCStatsCollectorTest,
1379 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001380 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001381 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001382 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001383
hbos9e302742017-01-20 02:47:10 -08001384 // Remote video track with values
1385 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
1386 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
1387 MediaStreamTrackInterface::kEnded);
1388 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(
1389 remote_video_track_ssrc3.get()));
1390
1391 cricket::VideoReceiverInfo video_receiver_info_ssrc3;
1392 video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
1393 video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
1394 video_receiver_info_ssrc3.frame_width = 6789;
1395 video_receiver_info_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001396 video_receiver_info_ssrc3.frames_received = 1000;
1397 video_receiver_info_ssrc3.frames_decoded = 995;
1398 video_receiver_info_ssrc3.frames_rendered = 990;
hbos9e302742017-01-20 02:47:10 -08001399
Steve Anton5b387312018-02-02 16:00:20 -08001400 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001401 {}, {}, {},
Harald Alvestrandc72af932018-01-11 17:18:19 +01001402 {std::make_pair(remote_video_track_ssrc3.get(),
Harald Alvestranda3dab842018-01-14 09:18:58 +01001403 video_receiver_info_ssrc3)},
1404 {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001405
Steve Anton5b387312018-02-02 16:00:20 -08001406 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001407
Harald Alvestranda3dab842018-01-14 09:18:58 +01001408 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
1409 ASSERT_EQ(1, stats_of_my_type.size()) << "No stream in " << report->ToJson();
1410 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1411 ASSERT_EQ(1, stats_of_track_type.size())
1412 << "Wrong number of tracks in " << report->ToJson();
1413 ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
hbos09bc1282016-11-08 06:29:22 -08001414
Harald Alvestranda3dab842018-01-14 09:18:58 +01001415 RTCMediaStreamStats expected_remote_stream(stats_of_my_type[0]->id(),
1416 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001417 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001418 expected_remote_stream.track_ids =
1419 std::vector<std::string>({stats_of_track_type[0]->id()});
hbosdbb64d82016-12-21 01:57:46 -08001420 ASSERT_TRUE(report->Get(expected_remote_stream.id()));
hbos09bc1282016-11-08 06:29:22 -08001421 EXPECT_EQ(expected_remote_stream,
1422 report->Get(expected_remote_stream.id())->cast_to<
1423 RTCMediaStreamStats>());
1424
hbos9e302742017-01-20 02:47:10 -08001425 RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001426 stats_of_track_type[0]->id(), report->timestamp_us(),
1427 RTCMediaStreamTrackKind::kVideo);
hbos9e302742017-01-20 02:47:10 -08001428 expected_remote_video_track_ssrc3.track_identifier =
1429 remote_video_track_ssrc3->id();
1430 expected_remote_video_track_ssrc3.remote_source = true;
1431 expected_remote_video_track_ssrc3.ended = true;
1432 expected_remote_video_track_ssrc3.detached = false;
1433 expected_remote_video_track_ssrc3.frame_width = 6789;
1434 expected_remote_video_track_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001435 expected_remote_video_track_ssrc3.frames_received = 1000;
1436 expected_remote_video_track_ssrc3.frames_decoded = 995;
1437 expected_remote_video_track_ssrc3.frames_dropped = 1000 - 990;
hbos9e302742017-01-20 02:47:10 -08001438 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
1439 EXPECT_EQ(expected_remote_video_track_ssrc3,
1440 report->Get(expected_remote_video_track_ssrc3.id())->cast_to<
1441 RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 06:29:22 -08001442}
1443
hboseeafe942016-11-01 03:00:17 -07001444TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
hboseeafe942016-11-01 03:00:17 -07001445 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001446
hboseeafe942016-11-01 03:00:17 -07001447 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1448 voice_media_info.receivers[0].local_stats.push_back(
1449 cricket::SsrcReceiverInfo());
1450 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001451 voice_media_info.receivers[0].packets_lost = -1; // Signed per RFC3550
hboseeafe942016-11-01 03:00:17 -07001452 voice_media_info.receivers[0].packets_rcvd = 2;
1453 voice_media_info.receivers[0].bytes_rcvd = 3;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001454 voice_media_info.receivers[0].codec_payload_type = 42;
hboseeafe942016-11-01 03:00:17 -07001455 voice_media_info.receivers[0].jitter_ms = 4500;
1456 voice_media_info.receivers[0].fraction_lost = 5.5f;
hbos0adb8282016-11-23 02:32:06 -08001457
1458 RtpCodecParameters codec_parameters;
1459 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001460 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1461 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001462 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001463 voice_media_info.receive_codecs.insert(
1464 std::make_pair(codec_parameters.payload_type, codec_parameters));
1465
Steve Anton57858b32018-02-15 15:19:50 -08001466 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001467 voice_media_channel->SetStats(voice_media_info);
1468 stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_AUDIO,
1469 "RemoteAudioTrackID", 1);
hboseeafe942016-11-01 03:00:17 -07001470
Steve Anton5b387312018-02-02 16:00:20 -08001471 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001472
Harald Alvestranda3dab842018-01-14 09:18:58 +01001473 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1474 ASSERT_EQ(1, stats_of_track_type.size());
1475
hboseeafe942016-11-01 03:00:17 -07001476 RTCInboundRTPStreamStats expected_audio(
1477 "RTCInboundRTPAudioStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001478 expected_audio.ssrc = 1;
hboseeafe942016-11-01 03:00:17 -07001479 expected_audio.is_remote = false;
1480 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001481 expected_audio.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001482 expected_audio.transport_id = "RTCTransport_TransportName_1";
1483 expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42";
hboseeafe942016-11-01 03:00:17 -07001484 expected_audio.packets_received = 2;
1485 expected_audio.bytes_received = 3;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001486 expected_audio.packets_lost = -1;
hboseeafe942016-11-01 03:00:17 -07001487 expected_audio.jitter = 4.5;
1488 expected_audio.fraction_lost = 5.5;
nissec8ee8822017-01-18 07:20:55 -08001489 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001490 EXPECT_EQ(
1491 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1492 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001493 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001494 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1495 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hboseeafe942016-11-01 03:00:17 -07001496}
1497
1498TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
hboseeafe942016-11-01 03:00:17 -07001499 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001500
hboseeafe942016-11-01 03:00:17 -07001501 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1502 video_media_info.receivers[0].local_stats.push_back(
1503 cricket::SsrcReceiverInfo());
1504 video_media_info.receivers[0].local_stats[0].ssrc = 1;
1505 video_media_info.receivers[0].packets_rcvd = 2;
hbos02cd4d62016-12-09 04:19:44 -08001506 video_media_info.receivers[0].packets_lost = 42;
hboseeafe942016-11-01 03:00:17 -07001507 video_media_info.receivers[0].bytes_rcvd = 3;
1508 video_media_info.receivers[0].fraction_lost = 4.5f;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001509 video_media_info.receivers[0].codec_payload_type = 42;
hbos820f5782016-11-22 03:16:50 -08001510 video_media_info.receivers[0].firs_sent = 5;
1511 video_media_info.receivers[0].plis_sent = 6;
1512 video_media_info.receivers[0].nacks_sent = 7;
hbos6769c492017-01-02 08:35:13 -08001513 video_media_info.receivers[0].frames_decoded = 8;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001514 video_media_info.receivers[0].qp_sum = rtc::nullopt;
hbos0adb8282016-11-23 02:32:06 -08001515
1516 RtpCodecParameters codec_parameters;
1517 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001518 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1519 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001520 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001521 video_media_info.receive_codecs.insert(
1522 std::make_pair(codec_parameters.payload_type, codec_parameters));
1523
Steve Anton57858b32018-02-15 15:19:50 -08001524 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001525 video_media_channel->SetStats(video_media_info);
1526 stats_->SetupRemoteTrackAndReceiver(cricket::MEDIA_TYPE_VIDEO,
1527 "RemoteVideoTrackID", 1);
hboseeafe942016-11-01 03:00:17 -07001528
Steve Anton5b387312018-02-02 16:00:20 -08001529 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001530
hbos820f5782016-11-22 03:16:50 -08001531 RTCInboundRTPStreamStats expected_video(
hboseeafe942016-11-01 03:00:17 -07001532 "RTCInboundRTPVideoStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001533 expected_video.ssrc = 1;
hbos820f5782016-11-22 03:16:50 -08001534 expected_video.is_remote = false;
1535 expected_video.media_type = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001536 expected_video.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001537 expected_video.transport_id = "RTCTransport_TransportName_1";
1538 expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42";
hbos820f5782016-11-22 03:16:50 -08001539 expected_video.fir_count = 5;
1540 expected_video.pli_count = 6;
1541 expected_video.nack_count = 7;
1542 expected_video.packets_received = 2;
1543 expected_video.bytes_received = 3;
hbos02cd4d62016-12-09 04:19:44 -08001544 expected_video.packets_lost = 42;
hbos820f5782016-11-22 03:16:50 -08001545 expected_video.fraction_lost = 4.5;
hbos6769c492017-01-02 08:35:13 -08001546 expected_video.frames_decoded = 8;
hbosa51d4f32017-02-16 05:34:48 -08001547 // |expected_video.qp_sum| should be undefined.
hboseeafe942016-11-01 03:00:17 -07001548
nissec8ee8822017-01-18 07:20:55 -08001549 ASSERT_TRUE(report->Get(expected_video.id()));
hbosa51d4f32017-02-16 05:34:48 -08001550 EXPECT_EQ(
1551 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1552 expected_video);
hboseeafe942016-11-01 03:00:17 -07001553
hbosa51d4f32017-02-16 05:34:48 -08001554 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001555 video_media_info.receivers[0].qp_sum = 9;
hbosa51d4f32017-02-16 05:34:48 -08001556 expected_video.qp_sum = 9;
Steve Anton5b387312018-02-02 16:00:20 -08001557 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001558
Steve Anton5b387312018-02-02 16:00:20 -08001559 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001560
1561 ASSERT_TRUE(report->Get(expected_video.id()));
1562 EXPECT_EQ(
1563 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1564 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08001565 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08001566 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbosa51d4f32017-02-16 05:34:48 -08001567 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hboseeafe942016-11-01 03:00:17 -07001568}
1569
hbos6ded1902016-11-01 01:50:46 -07001570TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
hbos6ded1902016-11-01 01:50:46 -07001571 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001572
hbos6ded1902016-11-01 01:50:46 -07001573 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1574 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1575 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1576 voice_media_info.senders[0].packets_sent = 2;
1577 voice_media_info.senders[0].bytes_sent = 3;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001578 voice_media_info.senders[0].codec_payload_type = 42;
hbos0adb8282016-11-23 02:32:06 -08001579
1580 RtpCodecParameters codec_parameters;
1581 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001582 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1583 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001584 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001585 voice_media_info.send_codecs.insert(
1586 std::make_pair(codec_parameters.payload_type, codec_parameters));
1587
Steve Anton57858b32018-02-15 15:19:50 -08001588 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001589 voice_media_channel->SetStats(voice_media_info);
1590 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
1591 "LocalAudioTrackID", 1, true);
hbos6ded1902016-11-01 01:50:46 -07001592
Steve Anton5b387312018-02-02 16:00:20 -08001593 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001594
1595 RTCOutboundRTPStreamStats expected_audio(
1596 "RTCOutboundRTPAudioStream_1", report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001597 expected_audio.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001598 expected_audio.is_remote = false;
1599 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001600 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001601 expected_audio.transport_id = "RTCTransport_TransportName_1";
1602 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001603 expected_audio.packets_sent = 2;
1604 expected_audio.bytes_sent = 3;
hboscd195be2017-02-07 08:31:27 -08001605
hboscd195be2017-02-07 08:31:27 -08001606 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001607 EXPECT_EQ(
1608 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1609 expected_audio);
skvladed02c6d2017-02-07 10:45:31 -08001610
hbosa51d4f32017-02-16 05:34:48 -08001611 ASSERT_TRUE(report->Get(expected_audio.id()));
1612 EXPECT_EQ(
1613 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1614 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001615 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001616 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1617 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001618}
1619
1620TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
hbos6ded1902016-11-01 01:50:46 -07001621 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001622
hbos6ded1902016-11-01 01:50:46 -07001623 video_media_info.senders.push_back(cricket::VideoSenderInfo());
1624 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1625 video_media_info.senders[0].local_stats[0].ssrc = 1;
1626 video_media_info.senders[0].firs_rcvd = 2;
1627 video_media_info.senders[0].plis_rcvd = 3;
1628 video_media_info.senders[0].nacks_rcvd = 4;
1629 video_media_info.senders[0].packets_sent = 5;
1630 video_media_info.senders[0].bytes_sent = 6;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001631 video_media_info.senders[0].codec_payload_type = 42;
hbos6769c492017-01-02 08:35:13 -08001632 video_media_info.senders[0].frames_encoded = 8;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001633 video_media_info.senders[0].qp_sum = rtc::nullopt;
hbos0adb8282016-11-23 02:32:06 -08001634
1635 RtpCodecParameters codec_parameters;
1636 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001637 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1638 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001639 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001640 video_media_info.send_codecs.insert(
1641 std::make_pair(codec_parameters.payload_type, codec_parameters));
1642
Steve Anton57858b32018-02-15 15:19:50 -08001643 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001644 video_media_channel->SetStats(video_media_info);
1645 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
1646 "LocalVideoTrackID", 1, true);
hbos6ded1902016-11-01 01:50:46 -07001647
Steve Anton5b387312018-02-02 16:00:20 -08001648 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001649
Harald Alvestranda3dab842018-01-14 09:18:58 +01001650 auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
1651 ASSERT_EQ(1, stats_of_my_type.size());
1652 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
1653 ASSERT_EQ(1, stats_of_track_type.size());
1654
1655 RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
1656 report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001657 expected_video.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001658 expected_video.is_remote = false;
1659 expected_video.media_type = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001660 expected_video.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001661 expected_video.transport_id = "RTCTransport_TransportName_1";
1662 expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001663 expected_video.fir_count = 2;
1664 expected_video.pli_count = 3;
1665 expected_video.nack_count = 4;
1666 expected_video.packets_sent = 5;
1667 expected_video.bytes_sent = 6;
skvladed02c6d2017-02-07 10:45:31 -08001668 expected_video.frames_encoded = 8;
hbosa7a9be12017-03-01 01:02:45 -08001669 // |expected_video.qp_sum| should be undefined.
hboscd195be2017-02-07 08:31:27 -08001670 ASSERT_TRUE(report->Get(expected_video.id()));
Harald Alvestranda3dab842018-01-14 09:18:58 +01001671
hbosa51d4f32017-02-16 05:34:48 -08001672 EXPECT_EQ(
1673 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
1674 expected_video);
skvladed02c6d2017-02-07 10:45:31 -08001675
hbosa51d4f32017-02-16 05:34:48 -08001676 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001677 video_media_info.senders[0].qp_sum = 9;
hbosa51d4f32017-02-16 05:34:48 -08001678 expected_video.qp_sum = 9;
Steve Anton5b387312018-02-02 16:00:20 -08001679 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001680
Steve Anton5b387312018-02-02 16:00:20 -08001681 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001682
1683 ASSERT_TRUE(report->Get(expected_video.id()));
1684 EXPECT_EQ(
1685 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
1686 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08001687 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08001688 EXPECT_TRUE(report->Get(*expected_video.transport_id));
1689 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001690}
1691
hbos2fa7c672016-10-24 04:00:05 -07001692TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
Steve Anton5b387312018-02-02 16:00:20 -08001693 const char kTransportName[] = "transport";
1694
1695 pc_->AddVoiceChannel("audio", kTransportName);
1696
Gary Liu37e489c2017-11-21 10:49:36 -08001697 std::unique_ptr<cricket::Candidate> rtp_local_candidate =
1698 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1699 cricket::LOCAL_PORT_TYPE, 42);
hbos2fa7c672016-10-24 04:00:05 -07001700 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
1701 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08001702 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
1703 42);
hbos2fa7c672016-10-24 04:00:05 -07001704 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
Gary Liu37e489c2017-11-21 10:49:36 -08001705 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
hbos2fa7c672016-10-24 04:00:05 -07001706 cricket::LOCAL_PORT_TYPE, 42);
1707 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
1708 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08001709 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
1710 42);
hbos2fa7c672016-10-24 04:00:05 -07001711
hbos2fa7c672016-10-24 04:00:05 -07001712 cricket::ConnectionInfo rtp_connection_info;
1713 rtp_connection_info.best_connection = false;
1714 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
1715 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
1716 rtp_connection_info.sent_total_bytes = 42;
1717 rtp_connection_info.recv_total_bytes = 1337;
1718 cricket::TransportChannelStats rtp_transport_channel_stats;
1719 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1720 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
hbos7064d592017-01-16 07:38:02 -08001721 rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
Steve Anton5b387312018-02-02 16:00:20 -08001722 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001723
1724 // Get stats without RTCP, an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08001725 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -08001726
1727 RTCTransportStats expected_rtp_transport(
1728 "RTCTransport_transport_" +
1729 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP),
1730 report->timestamp_us());
1731 expected_rtp_transport.bytes_sent = 42;
1732 expected_rtp_transport.bytes_received = 1337;
hbos7064d592017-01-16 07:38:02 -08001733 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
hbos0583b282016-11-30 01:50:14 -08001734
hbosdbb64d82016-12-21 01:57:46 -08001735 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001736 EXPECT_EQ(
1737 expected_rtp_transport,
1738 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001739
1740 cricket::ConnectionInfo rtcp_connection_info;
1741 rtcp_connection_info.best_connection = false;
1742 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
1743 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
1744 rtcp_connection_info.sent_total_bytes = 1337;
1745 rtcp_connection_info.recv_total_bytes = 42;
1746 cricket::TransportChannelStats rtcp_transport_channel_stats;
1747 rtcp_transport_channel_stats.component =
1748 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
1749 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
hbos7064d592017-01-16 07:38:02 -08001750 rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTING;
Steve Anton5b387312018-02-02 16:00:20 -08001751 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
1752 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001753
hbos2fa7c672016-10-24 04:00:05 -07001754 // Get stats with RTCP and without an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08001755 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001756
1757 RTCTransportStats expected_rtcp_transport(
1758 "RTCTransport_transport_" +
1759 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
1760 report->timestamp_us());
1761 expected_rtcp_transport.bytes_sent = 1337;
1762 expected_rtcp_transport.bytes_received = 42;
hbos7064d592017-01-16 07:38:02 -08001763 expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
hbos0583b282016-11-30 01:50:14 -08001764
1765 expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
1766
hbosdbb64d82016-12-21 01:57:46 -08001767 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001768 EXPECT_EQ(
1769 expected_rtp_transport,
1770 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001771 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001772 EXPECT_EQ(
1773 expected_rtcp_transport,
1774 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001775
hbos7064d592017-01-16 07:38:02 -08001776 // Get stats with an active connection (selected candidate pair).
Steve Anton5b387312018-02-02 16:00:20 -08001777 rtcp_transport_channel_stats.connection_infos[0].best_connection = true;
1778 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
1779 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07001780
Steve Anton5b387312018-02-02 16:00:20 -08001781 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001782
hbos0583b282016-11-30 01:50:14 -08001783 expected_rtcp_transport.selected_candidate_pair_id =
1784 "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" +
1785 rtcp_remote_candidate->id();
1786
hbosdbb64d82016-12-21 01:57:46 -08001787 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001788 EXPECT_EQ(
1789 expected_rtp_transport,
1790 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001791 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001792 EXPECT_EQ(
1793 expected_rtcp_transport,
1794 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001795
1796 // Get stats with certificates.
1797 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -08001798 CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
1799 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
hbos2fa7c672016-10-24 04:00:05 -07001800 std::unique_ptr<CertificateInfo> remote_certinfo =
1801 CreateFakeCertificateAndInfoFromDers(
Steve Anton5b387312018-02-02 16:00:20 -08001802 {"(remote) local", "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -08001803 pc_->SetRemoteCertChain(
Steve Anton5b387312018-02-02 16:00:20 -08001804 kTransportName,
Taylor Brandstetterc3928662018-02-23 13:04:51 -08001805 remote_certinfo->certificate->ssl_cert_chain().UniqueCopy());
hbos2fa7c672016-10-24 04:00:05 -07001806
Steve Anton5b387312018-02-02 16:00:20 -08001807 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08001808
1809 expected_rtp_transport.local_certificate_id =
1810 "RTCCertificate_" + local_certinfo->fingerprints[0];
1811 expected_rtp_transport.remote_certificate_id =
1812 "RTCCertificate_" + remote_certinfo->fingerprints[0];
1813
1814 expected_rtcp_transport.local_certificate_id =
1815 *expected_rtp_transport.local_certificate_id;
1816 expected_rtcp_transport.remote_certificate_id =
1817 *expected_rtp_transport.remote_certificate_id;
1818
hbosdbb64d82016-12-21 01:57:46 -08001819 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001820 EXPECT_EQ(
1821 expected_rtp_transport,
1822 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08001823 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08001824 EXPECT_EQ(
1825 expected_rtcp_transport,
1826 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07001827}
1828
Harald Alvestrand89061872018-01-02 14:08:34 +01001829TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
Harald Alvestrand89061872018-01-02 14:08:34 +01001830 cricket::VoiceMediaInfo voice_media_info;
1831
1832 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1833 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1834 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1835 voice_media_info.senders[0].packets_sent = 2;
1836 voice_media_info.senders[0].bytes_sent = 3;
1837 voice_media_info.senders[0].codec_payload_type = 42;
1838
1839 RtpCodecParameters codec_parameters;
1840 codec_parameters.payload_type = 42;
1841 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1842 codec_parameters.name = "dummy";
1843 codec_parameters.clock_rate = 0;
1844 voice_media_info.send_codecs.insert(
1845 std::make_pair(codec_parameters.payload_type, codec_parameters));
1846
Steve Anton5b387312018-02-02 16:00:20 -08001847 // Emulates the case where AddTrack is used without an associated MediaStream
Steve Anton57858b32018-02-15 15:19:50 -08001848 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001849 voice_media_channel->SetStats(voice_media_info);
1850 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
1851 "LocalAudioTrackID", 1, false);
Harald Alvestrand89061872018-01-02 14:08:34 +01001852
Steve Anton5b387312018-02-02 16:00:20 -08001853 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestrand89061872018-01-02 14:08:34 +01001854
1855 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
1856 report->timestamp_us());
1857 expected_audio.ssrc = 1;
1858 expected_audio.is_remote = false;
1859 expected_audio.media_type = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001860 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001861 expected_audio.transport_id = "RTCTransport_TransportName_1";
1862 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
Harald Alvestrand89061872018-01-02 14:08:34 +01001863 expected_audio.packets_sent = 2;
1864 expected_audio.bytes_sent = 3;
1865
1866 ASSERT_TRUE(report->Get(expected_audio.id()));
1867 EXPECT_EQ(
1868 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1869 expected_audio);
Harald Alvestrand89061872018-01-02 14:08:34 +01001870 EXPECT_TRUE(report->Get(*expected_audio.track_id));
1871 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1872 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
1873}
1874
1875// When the PC has not had SetLocalDescription done, tracks all have
1876// SSRC 0, meaning "unconnected".
Harald Alvestrandb8e12012018-01-23 15:28:16 +01001877// In this state, we report on track stats, but not RTP stats.
1878TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
Harald Alvestrand89061872018-01-02 14:08:34 +01001879 rtc::scoped_refptr<MediaStreamTrackInterface> track =
1880 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
1881 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08001882 rtc::scoped_refptr<MockRtpSenderInternal> sender =
1883 CreateMockSender(track, 0, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08001884 pc_->AddSender(sender);
1885
1886 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1887
Harald Alvestrand89061872018-01-02 14:08:34 +01001888 std::vector<const RTCMediaStreamTrackStats*> track_stats =
1889 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Harald Alvestrandb8e12012018-01-23 15:28:16 +01001890 EXPECT_EQ(1, track_stats.size());
Steve Anton5b387312018-02-02 16:00:20 -08001891
Harald Alvestrandb8e12012018-01-23 15:28:16 +01001892 std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
1893 report->GetStatsOfType<RTCRTPStreamStats>();
1894 EXPECT_EQ(0, rtp_stream_stats.size());
Harald Alvestrand89061872018-01-02 14:08:34 +01001895}
1896
Harald Alvestrand76d29522018-01-30 14:43:29 +01001897TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
1898 rtc::scoped_refptr<MediaStreamTrackInterface> track =
1899 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
1900 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08001901 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Harald Alvestrand76d29522018-01-30 14:43:29 +01001902 CreateMockSender(track, 4711, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08001903 pc_->AddSender(sender);
1904
Harald Alvestrand76d29522018-01-30 14:43:29 +01001905 // We do not generate any matching voice_sender_info stats.
Steve Anton5b387312018-02-02 16:00:20 -08001906 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
1907
Harald Alvestrand76d29522018-01-30 14:43:29 +01001908 std::vector<const RTCMediaStreamTrackStats*> track_stats =
1909 report->GetStatsOfType<RTCMediaStreamTrackStats>();
1910 EXPECT_EQ(1, track_stats.size());
1911}
1912
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08001913// Used for test below, to test calling GetStatsReport during a callback.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08001914class RecursiveCallback : public RTCStatsCollectorCallback {
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08001915 public:
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08001916 explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08001917
1918 void OnStatsDelivered(
1919 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
1920 stats_->GetStatsReport();
1921 called_ = true;
1922 }
1923
1924 bool called() const { return called_; }
1925
1926 private:
1927 RTCStatsCollectorWrapper* stats_;
1928 bool called_ = false;
1929};
1930
1931// Test that nothing bad happens if a callback causes GetStatsReport to be
1932// called again recursively. Regression test for crbug.com/webrtc/8973.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08001933TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
1934 rtc::scoped_refptr<RecursiveCallback> callback1(
1935 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
1936 rtc::scoped_refptr<RecursiveCallback> callback2(
1937 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08001938 stats_->stats_collector()->GetStatsReport(callback1);
1939 stats_->stats_collector()->GetStatsReport(callback2);
1940 EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
1941 EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
1942}
1943
Steve Anton5b387312018-02-02 16:00:20 -08001944class RTCTestStats : public RTCStats {
hbosc82f2e12016-09-05 01:36:50 -07001945 public:
Steve Anton5b387312018-02-02 16:00:20 -08001946 WEBRTC_RTCSTATS_DECL();
1947
1948 RTCTestStats(const std::string& id, int64_t timestamp_us)
1949 : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
1950
1951 RTCStatsMember<int32_t> dummy_stat;
1952};
1953
1954WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat);
1955
1956// Overrides the stats collection to verify thread usage and that the resulting
1957// partial reports are merged.
1958class FakeRTCStatsCollector : public RTCStatsCollector,
1959 public RTCStatsCollectorCallback {
1960 public:
1961 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
1962 PeerConnectionInternal* pc,
1963 int64_t cache_lifetime_us) {
1964 return rtc::scoped_refptr<FakeRTCStatsCollector>(
1965 new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
1966 cache_lifetime_us));
1967 }
1968
1969 // RTCStatsCollectorCallback implementation.
1970 void OnStatsDelivered(
1971 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
1972 EXPECT_TRUE(signaling_thread_->IsCurrent());
1973 rtc::CritScope cs(&lock_);
1974 delivered_report_ = report;
1975 }
1976
1977 void VerifyThreadUsageAndResultsMerging() {
1978 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
1979 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
1980 }
1981
1982 bool HasVerifiedResults() {
1983 EXPECT_TRUE(signaling_thread_->IsCurrent());
1984 rtc::CritScope cs(&lock_);
1985 if (!delivered_report_)
1986 return false;
1987 EXPECT_EQ(produced_on_signaling_thread_, 1);
1988 EXPECT_EQ(produced_on_network_thread_, 1);
1989
1990 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
1991 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
1992
1993 produced_on_signaling_thread_ = 0;
1994 produced_on_network_thread_ = 0;
1995 delivered_report_ = nullptr;
1996 return true;
hbosc82f2e12016-09-05 01:36:50 -07001997 }
1998
1999 protected:
Steve Anton5b387312018-02-02 16:00:20 -08002000 FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
2001 : RTCStatsCollector(pc, cache_lifetime),
2002 signaling_thread_(pc->signaling_thread()),
2003 worker_thread_(pc->worker_thread()),
2004 network_thread_(pc->network_thread()) {}
2005
2006 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
2007 EXPECT_TRUE(signaling_thread_->IsCurrent());
2008 {
2009 rtc::CritScope cs(&lock_);
2010 EXPECT_FALSE(delivered_report_);
2011 ++produced_on_signaling_thread_;
2012 }
2013
2014 rtc::scoped_refptr<RTCStatsReport> signaling_report =
2015 RTCStatsReport::Create(0);
2016 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
2017 new RTCTestStats("SignalingThreadStats", timestamp_us)));
2018 AddPartialResults(signaling_report);
2019 }
2020 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
2021 EXPECT_TRUE(network_thread_->IsCurrent());
2022 {
2023 rtc::CritScope cs(&lock_);
2024 EXPECT_FALSE(delivered_report_);
2025 ++produced_on_network_thread_;
2026 }
2027
2028 rtc::scoped_refptr<RTCStatsReport> network_report =
2029 RTCStatsReport::Create(0);
2030 network_report->AddStats(std::unique_ptr<const RTCStats>(
2031 new RTCTestStats("NetworkThreadStats", timestamp_us)));
2032 AddPartialResults(network_report);
2033 }
2034
2035 private:
2036 rtc::Thread* const signaling_thread_;
2037 rtc::Thread* const worker_thread_;
2038 rtc::Thread* const network_thread_;
2039
2040 rtc::CriticalSection lock_;
2041 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
2042 int produced_on_signaling_thread_ = 0;
2043 int produced_on_network_thread_ = 0;
hbosc82f2e12016-09-05 01:36:50 -07002044};
2045
Steve Anton5b387312018-02-02 16:00:20 -08002046TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
2047 rtc::scoped_refptr<FakePeerConnectionForStats> pc(
2048 new rtc::RefCountedObject<FakePeerConnectionForStats>());
2049 rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
2050 FakeRTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec));
2051 stats_collector->VerifyThreadUsageAndResultsMerging();
hbosc82f2e12016-09-05 01:36:50 -07002052}
2053
2054} // namespace
2055
hbosd565b732016-08-30 14:04:35 -07002056} // namespace webrtc