blob: 6cd63196a7fdb4873687604f0d4cb5f1b82b85f0 [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
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
Steve Anton1c9c9fc2019-02-14 15:13:09 -080019#include "absl/strings/str_replace.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "api/rtp_parameters.h"
21#include "api/stats/rtc_stats_report.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "api/stats/rtcstats_objects.h"
Sebastian Jansson5f83cf02018-05-08 14:52:22 +020023#include "api/units/time_delta.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "p2p/base/p2p_constants.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "p2p/base/port.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "pc/media_stream.h"
27#include "pc/media_stream_track.h"
28#include "pc/rtc_stats_collector.h"
29#include "pc/test/fake_peer_connection_for_stats.h"
30#include "pc/test/mock_data_channel.h"
31#include "pc/test/mock_rtp_receiver_internal.h"
32#include "pc/test/mock_rtp_sender_internal.h"
33#include "pc/test/rtc_stats_obtainer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "rtc_base/fake_clock.h"
36#include "rtc_base/fake_ssl_identity.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020037#include "rtc_base/gunit.h"
38#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080039#include "rtc_base/time_utils.h"
hbosd565b732016-08-30 14:04:35 -070040
Mirko Bonadei6a489f22019-04-09 15:11:12 +020041using ::testing::AtLeast;
42using ::testing::Invoke;
43using ::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
Henrik Boström646fda02019-05-22 15:49:42 +020092void PrintTo(const RTCAudioSourceStats& stats, ::std::ostream* os) {
93 *os << stats.ToJson();
94}
95
96void PrintTo(const RTCVideoSourceStats& stats, ::std::ostream* os) {
97 *os << stats.ToJson();
98}
99
hbosda389e32016-10-25 10:55:08 -0700100void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
ehmaldonado35a872c2017-07-28 07:29:12 -0700101 *os << stats.ToJson();
hbosda389e32016-10-25 10:55:08 -0700102}
103
hbosc82f2e12016-09-05 01:36:50 -0700104namespace {
105
106const int64_t kGetStatsReportTimeoutMs = 1000;
107
hbos6ab97ce2016-10-03 14:16:56 -0700108struct CertificateInfo {
109 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
110 std::vector<std::string> ders;
111 std::vector<std::string> pems;
112 std::vector<std::string> fingerprints;
113};
114
Harald Alvestranda3dab842018-01-14 09:18:58 +0100115// Return the ID for an object of the given type in a report.
116// The object must be present and be unique.
117template <typename T>
118std::string IdForType(const RTCStatsReport* report) {
119 auto stats_of_my_type = report->RTCStatsReport::GetStatsOfType<T>();
120 // We cannot use ASSERT here, since we're within a function.
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +0200121 EXPECT_EQ(1U, stats_of_my_type.size())
Harald Alvestranda3dab842018-01-14 09:18:58 +0100122 << "Unexpected number of stats of this type";
123 if (stats_of_my_type.size() == 1) {
124 return stats_of_my_type[0]->id();
125 } else {
126 // Return something that is not going to be a valid stas ID.
127 return "Type not found";
128 }
129}
130
hbos6ab97ce2016-10-03 14:16:56 -0700131std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
132 const std::vector<std::string>& ders) {
133 RTC_CHECK(!ders.empty());
134 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
135 info->ders = ders;
136 for (const std::string& der : ders) {
137 info->pems.push_back(rtc::SSLIdentity::DerToPem(
Yves Gerey665174f2018-06-19 15:03:05 +0200138 "CERTIFICATE", reinterpret_cast<const unsigned char*>(der.c_str()),
hbos6ab97ce2016-10-03 14:16:56 -0700139 der.length()));
140 }
141 info->certificate =
142 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800143 new rtc::FakeSSLIdentity(info->pems)));
hbos6ab97ce2016-10-03 14:16:56 -0700144 // Strip header/footer and newline characters of PEM strings.
145 for (size_t i = 0; i < info->pems.size(); ++i) {
Steve Anton1c9c9fc2019-02-14 15:13:09 -0800146 absl::StrReplaceAll({{"-----BEGIN CERTIFICATE-----", ""},
147 {"-----END CERTIFICATE-----", ""},
148 {"\n", ""}},
149 &info->pems[i]);
hbos6ab97ce2016-10-03 14:16:56 -0700150 }
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800151 // Fingerprints for the whole certificate chain, starting with leaf
152 // certificate.
Benjamin Wright6c6c9df2018-10-25 01:16:26 -0700153 const rtc::SSLCertChain& chain = info->certificate->GetSSLCertificateChain();
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800154 std::unique_ptr<rtc::SSLFingerprint> fp;
155 for (size_t i = 0; i < chain.GetSize(); i++) {
Steve Anton4905edb2018-10-15 19:27:44 -0700156 fp = rtc::SSLFingerprint::Create("sha-1", chain.Get(i));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800157 EXPECT_TRUE(fp);
158 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
hbos6ab97ce2016-10-03 14:16:56 -0700159 }
160 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
161 return info;
162}
163
hbosab9f6e42016-10-07 02:18:47 -0700164std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
165 const std::string& hostname,
166 int port,
167 const std::string& protocol,
Gary Liu37e489c2017-11-21 10:49:36 -0800168 const rtc::AdapterType adapter_type,
hbosab9f6e42016-10-07 02:18:47 -0700169 const std::string& candidate_type,
170 uint32_t priority) {
171 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
172 candidate->set_address(rtc::SocketAddress(hostname, port));
173 candidate->set_protocol(protocol);
Gary Liu37e489c2017-11-21 10:49:36 -0800174 candidate->set_network_type(adapter_type);
hbosab9f6e42016-10-07 02:18:47 -0700175 candidate->set_type(candidate_type);
176 candidate->set_priority(priority);
177 return candidate;
178}
179
Yves Gerey665174f2018-06-19 15:03:05 +0200180class FakeAudioTrackForStats : public MediaStreamTrack<AudioTrackInterface> {
hbos09bc1282016-11-08 06:29:22 -0800181 public:
182 static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
183 const std::string& id,
hbos9e302742017-01-20 02:47:10 -0800184 MediaStreamTrackInterface::TrackState state) {
hbos09bc1282016-11-08 06:29:22 -0800185 rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
hbos9e302742017-01-20 02:47:10 -0800186 new rtc::RefCountedObject<FakeAudioTrackForStats>(id));
hbos09bc1282016-11-08 06:29:22 -0800187 audio_track_stats->set_state(state);
188 return audio_track_stats;
189 }
190
Steve Anton36b29d12017-10-30 09:57:42 -0700191 explicit FakeAudioTrackForStats(const std::string& id)
192 : MediaStreamTrack<AudioTrackInterface>(id) {}
hbos09bc1282016-11-08 06:29:22 -0800193
194 std::string kind() const override {
195 return MediaStreamTrackInterface::kAudioKind;
196 }
197 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
198 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
199 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
hbos9e302742017-01-20 02:47:10 -0800200 bool GetSignalLevel(int* level) override { return false; }
hbos09bc1282016-11-08 06:29:22 -0800201 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
hbos9e302742017-01-20 02:47:10 -0800202 return nullptr;
hbos09bc1282016-11-08 06:29:22 -0800203 }
hbos09bc1282016-11-08 06:29:22 -0800204};
205
Henrik Boström646fda02019-05-22 15:49:42 +0200206class FakeVideoTrackSourceForStats : public VideoTrackSourceInterface {
207 public:
208 static rtc::scoped_refptr<FakeVideoTrackSourceForStats> Create(
209 int input_width,
210 int input_height) {
211 return rtc::scoped_refptr<FakeVideoTrackSourceForStats>(
212 new rtc::RefCountedObject<FakeVideoTrackSourceForStats>(input_width,
213 input_height));
214 }
215
216 FakeVideoTrackSourceForStats(int input_width, int input_height)
217 : input_width_(input_width), input_height_(input_height) {}
218 ~FakeVideoTrackSourceForStats() override {}
219
220 // VideoTrackSourceInterface
221 bool is_screencast() const override { return false; }
222 absl::optional<bool> needs_denoising() const override { return false; }
223 bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
224 stats->input_width = input_width_;
225 stats->input_height = input_height_;
226 return true;
227 }
228 // MediaSourceInterface (part of VideoTrackSourceInterface)
229 MediaSourceInterface::SourceState state() const override {
230 return MediaSourceInterface::SourceState::kLive;
231 }
232 bool remote() const override { return false; }
233 // NotifierInterface (part of MediaSourceInterface)
234 void RegisterObserver(ObserverInterface* observer) override {}
235 void UnregisterObserver(ObserverInterface* observer) override {}
236 // rtc::VideoSourceInterface<VideoFrame> (part of VideoTrackSourceInterface)
237 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
238 const rtc::VideoSinkWants& wants) override {}
239 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
240
241 private:
242 int input_width_;
243 int input_height_;
244};
245
Yves Gerey665174f2018-06-19 15:03:05 +0200246class FakeVideoTrackForStats : public MediaStreamTrack<VideoTrackInterface> {
hbos09bc1282016-11-08 06:29:22 -0800247 public:
248 static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
249 const std::string& id,
Henrik Boström646fda02019-05-22 15:49:42 +0200250 MediaStreamTrackInterface::TrackState state,
251 rtc::scoped_refptr<VideoTrackSourceInterface> source) {
hbos09bc1282016-11-08 06:29:22 -0800252 rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
Henrik Boström646fda02019-05-22 15:49:42 +0200253 new rtc::RefCountedObject<FakeVideoTrackForStats>(id,
254 std::move(source)));
hbos09bc1282016-11-08 06:29:22 -0800255 video_track->set_state(state);
256 return video_track;
257 }
258
Henrik Boström646fda02019-05-22 15:49:42 +0200259 FakeVideoTrackForStats(const std::string& id,
260 rtc::scoped_refptr<VideoTrackSourceInterface> source)
261 : MediaStreamTrack<VideoTrackInterface>(id), source_(source) {}
hbos09bc1282016-11-08 06:29:22 -0800262
263 std::string kind() const override {
264 return MediaStreamTrackInterface::kVideoKind;
265 }
perkj773be362017-07-31 23:22:01 -0700266
267 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100268 const rtc::VideoSinkWants& wants) override {}
269 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
perkj773be362017-07-31 23:22:01 -0700270
Henrik Boström646fda02019-05-22 15:49:42 +0200271 VideoTrackSourceInterface* GetSource() const override {
272 return source_.get();
273 }
274
275 private:
276 rtc::scoped_refptr<VideoTrackSourceInterface> source_;
hbos09bc1282016-11-08 06:29:22 -0800277};
278
hbos84abeb12017-01-16 06:16:44 -0800279rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack(
280 cricket::MediaType media_type,
hbos9e302742017-01-20 02:47:10 -0800281 const std::string& track_id,
282 MediaStreamTrackInterface::TrackState track_state) {
hbos84abeb12017-01-16 06:16:44 -0800283 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800284 return FakeAudioTrackForStats::Create(track_id, track_state);
hbos84abeb12017-01-16 06:16:44 -0800285 } else {
286 RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
Henrik Boström646fda02019-05-22 15:49:42 +0200287 return FakeVideoTrackForStats::Create(track_id, track_state, nullptr);
hbos84abeb12017-01-16 06:16:44 -0800288 }
289}
290
Steve Anton57858b32018-02-15 15:19:50 -0800291rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
Henrik Boström646fda02019-05-22 15:49:42 +0200292 cricket::MediaType media_type,
293 rtc::scoped_refptr<MediaStreamTrackInterface> track,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100294 uint32_t ssrc,
Harald Alvestranda3dab842018-01-14 09:18:58 +0100295 int attachment_id,
296 std::vector<std::string> local_stream_ids) {
Henrik Boström646fda02019-05-22 15:49:42 +0200297 RTC_DCHECK(!track ||
298 (track->kind() == MediaStreamTrackInterface::kAudioKind &&
299 media_type == cricket::MEDIA_TYPE_AUDIO) ||
300 (track->kind() == MediaStreamTrackInterface::kVideoKind &&
301 media_type == cricket::MEDIA_TYPE_VIDEO));
Steve Anton57858b32018-02-15 15:19:50 -0800302 rtc::scoped_refptr<MockRtpSenderInternal> sender(
303 new rtc::RefCountedObject<MockRtpSenderInternal>());
hbos9e302742017-01-20 02:47:10 -0800304 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
305 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
Henrik Boström646fda02019-05-22 15:49:42 +0200306 EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return(media_type));
Yves Gerey665174f2018-06-19 15:03:05 +0200307 EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
308 RtpParameters params;
309 params.encodings.push_back(RtpEncodingParameters());
310 params.encodings[0].ssrc = ssrc;
311 return params;
312 }));
Harald Alvestrandc72af932018-01-11 17:18:19 +0100313 EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
Harald Alvestranda3dab842018-01-14 09:18:58 +0100314 EXPECT_CALL(*sender, stream_ids()).WillRepeatedly(Return(local_stream_ids));
hbos9e302742017-01-20 02:47:10 -0800315 return sender;
316}
317
Steve Anton57858b32018-02-15 15:19:50 -0800318rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
Mirko Bonadeic61ce0d2017-11-21 17:04:20 +0100319 const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100320 uint32_t ssrc,
321 int attachment_id) {
Steve Anton57858b32018-02-15 15:19:50 -0800322 rtc::scoped_refptr<MockRtpReceiverInternal> receiver(
323 new rtc::RefCountedObject<MockRtpReceiverInternal>());
hbos9e302742017-01-20 02:47:10 -0800324 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
Harald Alvestranda3dab842018-01-14 09:18:58 +0100325 EXPECT_CALL(*receiver, streams())
326 .WillRepeatedly(
327 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>({})));
328
Yves Gerey665174f2018-06-19 15:03:05 +0200329 EXPECT_CALL(*receiver, media_type())
330 .WillRepeatedly(
331 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
332 ? cricket::MEDIA_TYPE_AUDIO
333 : cricket::MEDIA_TYPE_VIDEO));
334 EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke([ssrc]() {
335 RtpParameters params;
336 params.encodings.push_back(RtpEncodingParameters());
337 params.encodings[0].ssrc = ssrc;
338 return params;
339 }));
Harald Alvestrandc72af932018-01-11 17:18:19 +0100340 EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
hbos9e302742017-01-20 02:47:10 -0800341 return receiver;
342}
343
Steve Anton5b387312018-02-02 16:00:20 -0800344class RTCStatsCollectorWrapper {
hbosd565b732016-08-30 14:04:35 -0700345 public:
Steve Anton5b387312018-02-02 16:00:20 -0800346 explicit RTCStatsCollectorWrapper(
347 rtc::scoped_refptr<FakePeerConnectionForStats> pc)
348 : pc_(pc),
349 stats_collector_(
350 RTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec)) {
hbosd565b732016-08-30 14:04:35 -0700351 }
352
Steve Anton5b387312018-02-02 16:00:20 -0800353 rtc::scoped_refptr<RTCStatsCollector> stats_collector() {
354 return stats_collector_;
hbosd565b732016-08-30 14:04:35 -0700355 }
356
Henrik Boström5b3541f2018-03-19 13:52:56 +0100357 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
358 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
359 stats_collector_->GetStatsReport(callback);
360 return WaitForReport(callback);
361 }
362
363 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithSenderSelector(
364 rtc::scoped_refptr<RtpSenderInternal> selector) {
365 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
366 stats_collector_->GetStatsReport(selector, callback);
367 return WaitForReport(callback);
368 }
369
370 rtc::scoped_refptr<const RTCStatsReport> GetStatsReportWithReceiverSelector(
371 rtc::scoped_refptr<RtpReceiverInternal> selector) {
372 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create();
373 stats_collector_->GetStatsReport(selector, callback);
374 return WaitForReport(callback);
375 }
376
Steve Anton5b387312018-02-02 16:00:20 -0800377 rtc::scoped_refptr<const RTCStatsReport> GetFreshStatsReport() {
378 stats_collector_->ClearCachedStatsReport();
379 return GetStatsReport();
380 }
381
Henrik Boström5b3541f2018-03-19 13:52:56 +0100382 rtc::scoped_refptr<MockRtpSenderInternal> SetupLocalTrackAndSender(
383 cricket::MediaType media_type,
384 const std::string& track_id,
385 uint32_t ssrc,
Henrik Boström646fda02019-05-22 15:49:42 +0200386 bool add_stream,
387 int attachment_id) {
Harald Alvestrand89061872018-01-02 14:08:34 +0100388 rtc::scoped_refptr<MediaStream> local_stream;
389 if (add_stream) {
Seth Hampson845e8782018-03-02 11:34:10 -0800390 local_stream = MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -0800391 pc_->mutable_local_streams()->AddStream(local_stream);
Harald Alvestrand89061872018-01-02 14:08:34 +0100392 }
hbos84abeb12017-01-16 06:16:44 -0800393
394 rtc::scoped_refptr<MediaStreamTrackInterface> track;
395 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800396 track = CreateFakeTrack(media_type, track_id,
397 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100398 if (add_stream) {
399 local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
400 }
hbos84abeb12017-01-16 06:16:44 -0800401 } else {
hbos9e302742017-01-20 02:47:10 -0800402 track = CreateFakeTrack(media_type, track_id,
403 MediaStreamTrackInterface::kLive);
Harald Alvestrand89061872018-01-02 14:08:34 +0100404 if (add_stream) {
405 local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
406 }
hbos84abeb12017-01-16 06:16:44 -0800407 }
408
Steve Anton57858b32018-02-15 15:19:50 -0800409 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 15:49:42 +0200410 CreateMockSender(media_type, track, ssrc, attachment_id, {});
Steve Anton5b387312018-02-02 16:00:20 -0800411 pc_->AddSender(sender);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100412 return sender;
hbos84abeb12017-01-16 06:16:44 -0800413 }
414
Henrik Boström5b3541f2018-03-19 13:52:56 +0100415 rtc::scoped_refptr<MockRtpReceiverInternal> SetupRemoteTrackAndReceiver(
416 cricket::MediaType media_type,
417 const std::string& track_id,
418 const std::string& stream_id,
419 uint32_t ssrc) {
hbos84abeb12017-01-16 06:16:44 -0800420 rtc::scoped_refptr<MediaStream> remote_stream =
Henrik Boström5b3541f2018-03-19 13:52:56 +0100421 MediaStream::Create(stream_id);
Steve Anton5b387312018-02-02 16:00:20 -0800422 pc_->mutable_remote_streams()->AddStream(remote_stream);
hbos84abeb12017-01-16 06:16:44 -0800423
424 rtc::scoped_refptr<MediaStreamTrackInterface> track;
425 if (media_type == cricket::MEDIA_TYPE_AUDIO) {
hbos9e302742017-01-20 02:47:10 -0800426 track = CreateFakeTrack(media_type, track_id,
427 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800428 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get()));
429 } else {
hbos9e302742017-01-20 02:47:10 -0800430 track = CreateFakeTrack(media_type, track_id,
431 MediaStreamTrackInterface::kLive);
hbos84abeb12017-01-16 06:16:44 -0800432 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get()));
433 }
434
Steve Anton57858b32018-02-15 15:19:50 -0800435 rtc::scoped_refptr<MockRtpReceiverInternal> receiver =
Harald Alvestrandc72af932018-01-11 17:18:19 +0100436 CreateMockReceiver(track, ssrc, 62);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100437 EXPECT_CALL(*receiver, streams())
438 .WillRepeatedly(
439 Return(std::vector<rtc::scoped_refptr<MediaStreamInterface>>(
440 {remote_stream})));
Steve Anton5b387312018-02-02 16:00:20 -0800441 pc_->AddReceiver(receiver);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100442 return receiver;
hbos84abeb12017-01-16 06:16:44 -0800443 }
444
hbos9e302742017-01-20 02:47:10 -0800445 // Attaches tracks to peer connections by configuring RTP senders and RTP
446 // receivers according to the tracks' pairings with
447 // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be
448 // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only
449 // be associated with one |[Voice/Video]ReceiverInfo|.
Henrik Boström646fda02019-05-22 15:49:42 +0200450 // Senders get assigned attachment ID "ssrc + 10".
hbos9e302742017-01-20 02:47:10 -0800451 void CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +0100452 std::initializer_list<
453 std::pair<MediaStreamTrackInterface*, cricket::VoiceSenderInfo>>
454 local_audio_track_info_pairs,
455 std::initializer_list<
456 std::pair<MediaStreamTrackInterface*, cricket::VoiceReceiverInfo>>
457 remote_audio_track_info_pairs,
458 std::initializer_list<
459 std::pair<MediaStreamTrackInterface*, cricket::VideoSenderInfo>>
460 local_video_track_info_pairs,
461 std::initializer_list<
462 std::pair<MediaStreamTrackInterface*, cricket::VideoReceiverInfo>>
463 remote_video_track_info_pairs,
464 std::vector<std::string> local_stream_ids,
465 std::vector<rtc::scoped_refptr<MediaStreamInterface>> remote_streams) {
Steve Anton5b387312018-02-02 16:00:20 -0800466 cricket::VoiceMediaInfo voice_media_info;
467 cricket::VideoMediaInfo video_media_info;
468
hbos9e302742017-01-20 02:47:10 -0800469 // Local audio tracks and voice sender infos
470 for (auto& pair : local_audio_track_info_pairs) {
471 MediaStreamTrackInterface* local_audio_track = pair.first;
472 const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
473 RTC_DCHECK_EQ(local_audio_track->kind(),
474 MediaStreamTrackInterface::kAudioKind);
475
Steve Anton5b387312018-02-02 16:00:20 -0800476 voice_media_info.senders.push_back(voice_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800477 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Henrik Boström646fda02019-05-22 15:49:42 +0200478 cricket::MEDIA_TYPE_AUDIO,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100479 rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
Henrik Boström646fda02019-05-22 15:49:42 +0200480 voice_sender_info.local_stats[0].ssrc,
481 voice_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800482 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800483 }
Steve Anton5b387312018-02-02 16:00:20 -0800484
hbos9e302742017-01-20 02:47:10 -0800485 // Remote audio tracks and voice receiver infos
486 for (auto& pair : remote_audio_track_info_pairs) {
487 MediaStreamTrackInterface* remote_audio_track = pair.first;
488 const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
489 RTC_DCHECK_EQ(remote_audio_track->kind(),
490 MediaStreamTrackInterface::kAudioKind);
491
Steve Anton5b387312018-02-02 16:00:20 -0800492 voice_media_info.receivers.push_back(voice_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800493 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
494 CreateMockReceiver(
495 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
Henrik Boström646fda02019-05-22 15:49:42 +0200496 voice_receiver_info.local_stats[0].ssrc,
497 voice_receiver_info.local_stats[0].ssrc + 10);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100498 EXPECT_CALL(*rtp_receiver, streams())
499 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800500 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800501 }
Steve Anton5b387312018-02-02 16:00:20 -0800502
hbos9e302742017-01-20 02:47:10 -0800503 // Local video tracks and video sender infos
504 for (auto& pair : local_video_track_info_pairs) {
505 MediaStreamTrackInterface* local_video_track = pair.first;
506 const cricket::VideoSenderInfo& video_sender_info = pair.second;
507 RTC_DCHECK_EQ(local_video_track->kind(),
508 MediaStreamTrackInterface::kVideoKind);
509
Steve Anton5b387312018-02-02 16:00:20 -0800510 video_media_info.senders.push_back(video_sender_info);
Steve Anton57858b32018-02-15 15:19:50 -0800511 rtc::scoped_refptr<MockRtpSenderInternal> rtp_sender = CreateMockSender(
Henrik Boström646fda02019-05-22 15:49:42 +0200512 cricket::MEDIA_TYPE_VIDEO,
Harald Alvestrandc72af932018-01-11 17:18:19 +0100513 rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
Henrik Boström646fda02019-05-22 15:49:42 +0200514 video_sender_info.local_stats[0].ssrc,
515 video_sender_info.local_stats[0].ssrc + 10, local_stream_ids);
Steve Anton5b387312018-02-02 16:00:20 -0800516 pc_->AddSender(rtp_sender);
hbos9e302742017-01-20 02:47:10 -0800517 }
Steve Anton5b387312018-02-02 16:00:20 -0800518
hbos9e302742017-01-20 02:47:10 -0800519 // Remote video tracks and video receiver infos
520 for (auto& pair : remote_video_track_info_pairs) {
521 MediaStreamTrackInterface* remote_video_track = pair.first;
522 const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
523 RTC_DCHECK_EQ(remote_video_track->kind(),
524 MediaStreamTrackInterface::kVideoKind);
525
Steve Anton5b387312018-02-02 16:00:20 -0800526 video_media_info.receivers.push_back(video_receiver_info);
Steve Anton57858b32018-02-15 15:19:50 -0800527 rtc::scoped_refptr<MockRtpReceiverInternal> rtp_receiver =
528 CreateMockReceiver(
529 rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
Henrik Boström646fda02019-05-22 15:49:42 +0200530 video_receiver_info.local_stats[0].ssrc,
531 video_receiver_info.local_stats[0].ssrc + 10);
Harald Alvestranda3dab842018-01-14 09:18:58 +0100532 EXPECT_CALL(*rtp_receiver, streams())
533 .WillRepeatedly(Return(remote_streams));
Steve Anton5b387312018-02-02 16:00:20 -0800534 pc_->AddReceiver(rtp_receiver);
hbos9e302742017-01-20 02:47:10 -0800535 }
hbos9e302742017-01-20 02:47:10 -0800536
Steve Anton5b387312018-02-02 16:00:20 -0800537 auto* voice_media_channel = pc_->AddVoiceChannel("audio", "transport");
538 voice_media_channel->SetStats(voice_media_info);
hbos9e302742017-01-20 02:47:10 -0800539
Steve Anton5b387312018-02-02 16:00:20 -0800540 auto* video_media_channel = pc_->AddVideoChannel("video", "transport");
541 video_media_channel->SetStats(video_media_info);
hbos9e302742017-01-20 02:47:10 -0800542 }
543
hbosd565b732016-08-30 14:04:35 -0700544 private:
Henrik Boström5b3541f2018-03-19 13:52:56 +0100545 rtc::scoped_refptr<const RTCStatsReport> WaitForReport(
546 rtc::scoped_refptr<RTCStatsObtainer> callback) {
547 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
548 int64_t after = rtc::TimeUTCMicros();
549 for (const RTCStats& stats : *callback->report()) {
550 EXPECT_LE(stats.timestamp_us(), after);
551 }
552 return callback->report();
553 }
554
Steve Anton5b387312018-02-02 16:00:20 -0800555 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
556 rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
hbosd565b732016-08-30 14:04:35 -0700557};
558
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200559class RTCStatsCollectorTest : public ::testing::Test {
hbosc82f2e12016-09-05 01:36:50 -0700560 public:
561 RTCStatsCollectorTest()
Steve Anton5b387312018-02-02 16:00:20 -0800562 : pc_(new rtc::RefCountedObject<FakePeerConnectionForStats>()),
563 stats_(new RTCStatsCollectorWrapper(pc_)) {}
hbosc82f2e12016-09-05 01:36:50 -0700564
hbos6ab97ce2016-10-03 14:16:56 -0700565 void ExpectReportContainsCertificateInfo(
566 const rtc::scoped_refptr<const RTCStatsReport>& report,
hbos23368e12016-12-21 04:29:17 -0800567 const CertificateInfo& certinfo) {
568 for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) {
569 RTCCertificateStats expected_certificate_stats(
Yves Gerey665174f2018-06-19 15:03:05 +0200570 "RTCCertificate_" + certinfo.fingerprints[i], report->timestamp_us());
hbos23368e12016-12-21 04:29:17 -0800571 expected_certificate_stats.fingerprint = certinfo.fingerprints[i];
572 expected_certificate_stats.fingerprint_algorithm = "sha-1";
573 expected_certificate_stats.base64_certificate = certinfo.pems[i];
574 if (i + 1 < certinfo.fingerprints.size()) {
575 expected_certificate_stats.issuer_certificate_id =
576 "RTCCertificate_" + certinfo.fingerprints[i + 1];
hbos6ab97ce2016-10-03 14:16:56 -0700577 }
hbos23368e12016-12-21 04:29:17 -0800578 ASSERT_TRUE(report->Get(expected_certificate_stats.id()));
579 EXPECT_EQ(expected_certificate_stats,
Yves Gerey665174f2018-06-19 15:03:05 +0200580 report->Get(expected_certificate_stats.id())
581 ->cast_to<RTCCertificateStats>());
hbos6ab97ce2016-10-03 14:16:56 -0700582 }
583 }
584
Henrik Boström5b3541f2018-03-19 13:52:56 +0100585 struct ExampleStatsGraph {
586 rtc::scoped_refptr<RtpSenderInternal> sender;
587 rtc::scoped_refptr<RtpReceiverInternal> receiver;
588
589 rtc::scoped_refptr<const RTCStatsReport> full_report;
590 std::string send_codec_id;
591 std::string recv_codec_id;
592 std::string outbound_rtp_id;
593 std::string inbound_rtp_id;
594 std::string transport_id;
595 std::string sender_track_id;
596 std::string receiver_track_id;
597 std::string remote_stream_id;
598 std::string peer_connection_id;
Henrik Boström646fda02019-05-22 15:49:42 +0200599 std::string media_source_id;
Henrik Boström5b3541f2018-03-19 13:52:56 +0100600 };
601
602 // Sets up the example stats graph (see ASCII art below) used for testing the
603 // stats selection algorithm,
604 // https://w3c.github.io/webrtc-pc/#dfn-stats-selection-algorithm.
605 // These tests test the integration of the stats traversal algorithm inside of
606 // RTCStatsCollector. See rtcstatstraveral_unittest.cc for more stats
607 // traversal tests.
608 ExampleStatsGraph SetupExampleStatsGraphForSelectorTests() {
609 ExampleStatsGraph graph;
610
611 // codec (send)
612 graph.send_codec_id = "RTCCodec_VideoMid_Outbound_1";
613 cricket::VideoMediaInfo video_media_info;
614 RtpCodecParameters send_codec;
615 send_codec.payload_type = 1;
616 send_codec.clock_rate = 0;
617 video_media_info.send_codecs.insert(
618 std::make_pair(send_codec.payload_type, send_codec));
619 // codec (recv)
620 graph.recv_codec_id = "RTCCodec_VideoMid_Inbound_2";
621 RtpCodecParameters recv_codec;
622 recv_codec.payload_type = 2;
623 recv_codec.clock_rate = 0;
624 video_media_info.receive_codecs.insert(
625 std::make_pair(recv_codec.payload_type, recv_codec));
626 // outbound-rtp
627 graph.outbound_rtp_id = "RTCOutboundRTPVideoStream_3";
628 video_media_info.senders.push_back(cricket::VideoSenderInfo());
629 video_media_info.senders[0].local_stats.push_back(
630 cricket::SsrcSenderInfo());
631 video_media_info.senders[0].local_stats[0].ssrc = 3;
632 video_media_info.senders[0].codec_payload_type = send_codec.payload_type;
633 // inbound-rtp
634 graph.inbound_rtp_id = "RTCInboundRTPVideoStream_4";
635 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
636 video_media_info.receivers[0].local_stats.push_back(
637 cricket::SsrcReceiverInfo());
638 video_media_info.receivers[0].local_stats[0].ssrc = 4;
639 video_media_info.receivers[0].codec_payload_type = recv_codec.payload_type;
640 // transport
641 graph.transport_id = "RTCTransport_TransportName_1";
642 auto* video_media_channel =
643 pc_->AddVideoChannel("VideoMid", "TransportName");
644 video_media_channel->SetStats(video_media_info);
645 // track (sender)
646 graph.sender = stats_->SetupLocalTrackAndSender(
Henrik Boström646fda02019-05-22 15:49:42 +0200647 cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 3, false, 50);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100648 graph.sender_track_id = "RTCMediaStreamTrack_sender_" +
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200649 rtc::ToString(graph.sender->AttachmentId());
Henrik Boström5b3541f2018-03-19 13:52:56 +0100650 // track (receiver) and stream (remote stream)
651 graph.receiver = stats_->SetupRemoteTrackAndReceiver(
652 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 4);
653 graph.receiver_track_id = "RTCMediaStreamTrack_receiver_" +
Jonas Olsson6b1985d2018-07-05 11:59:48 +0200654 rtc::ToString(graph.receiver->AttachmentId());
Henrik Boström5b3541f2018-03-19 13:52:56 +0100655 graph.remote_stream_id = "RTCMediaStream_RemoteStreamId";
656 // peer-connection
657 graph.peer_connection_id = "RTCPeerConnection";
Henrik Boström646fda02019-05-22 15:49:42 +0200658 // media-source (kind: video)
659 graph.media_source_id =
660 "RTCVideoSource_" + rtc::ToString(graph.sender->AttachmentId());
Henrik Boström5b3541f2018-03-19 13:52:56 +0100661
662 // Expected stats graph:
663 //
Henrik Boström646fda02019-05-22 15:49:42 +0200664 // +--- track (sender) stream (remote stream) ---> track (receiver)
665 // | ^ ^
666 // | | |
667 // | +--------- outbound-rtp inbound-rtp ---------------+
668 // | | | | | |
669 // | | v v v v
670 // | | codec (send) transport codec (recv) peer-connection
671 // v v
672 // media-source
Henrik Boström5b3541f2018-03-19 13:52:56 +0100673
674 // Verify the stats graph is set up correctly.
675 graph.full_report = stats_->GetStatsReport();
Henrik Boström646fda02019-05-22 15:49:42 +0200676 EXPECT_EQ(graph.full_report->size(), 10u);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100677 EXPECT_TRUE(graph.full_report->Get(graph.send_codec_id));
678 EXPECT_TRUE(graph.full_report->Get(graph.recv_codec_id));
679 EXPECT_TRUE(graph.full_report->Get(graph.outbound_rtp_id));
680 EXPECT_TRUE(graph.full_report->Get(graph.inbound_rtp_id));
681 EXPECT_TRUE(graph.full_report->Get(graph.transport_id));
682 EXPECT_TRUE(graph.full_report->Get(graph.sender_track_id));
683 EXPECT_TRUE(graph.full_report->Get(graph.receiver_track_id));
684 EXPECT_TRUE(graph.full_report->Get(graph.remote_stream_id));
685 EXPECT_TRUE(graph.full_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 15:49:42 +0200686 EXPECT_TRUE(graph.full_report->Get(graph.media_source_id));
687 const auto& sender_track = graph.full_report->Get(graph.sender_track_id)
688 ->cast_to<RTCMediaStreamTrackStats>();
689 EXPECT_EQ(*sender_track.media_source_id, graph.media_source_id);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100690 const auto& outbound_rtp = graph.full_report->Get(graph.outbound_rtp_id)
691 ->cast_to<RTCOutboundRTPStreamStats>();
Henrik Boström646fda02019-05-22 15:49:42 +0200692 EXPECT_EQ(*outbound_rtp.media_source_id, graph.media_source_id);
Henrik Boström5b3541f2018-03-19 13:52:56 +0100693 EXPECT_EQ(*outbound_rtp.codec_id, graph.send_codec_id);
694 EXPECT_EQ(*outbound_rtp.track_id, graph.sender_track_id);
695 EXPECT_EQ(*outbound_rtp.transport_id, graph.transport_id);
696 const auto& inbound_rtp = graph.full_report->Get(graph.inbound_rtp_id)
697 ->cast_to<RTCInboundRTPStreamStats>();
698 EXPECT_EQ(*inbound_rtp.codec_id, graph.recv_codec_id);
699 EXPECT_EQ(*inbound_rtp.track_id, graph.receiver_track_id);
700 EXPECT_EQ(*inbound_rtp.transport_id, graph.transport_id);
701
702 return graph;
703 }
704
hbosc82f2e12016-09-05 01:36:50 -0700705 protected:
Steve Anton5b387312018-02-02 16:00:20 -0800706 rtc::ScopedFakeClock fake_clock_;
707 rtc::scoped_refptr<FakePeerConnectionForStats> pc_;
708 std::unique_ptr<RTCStatsCollectorWrapper> stats_;
hbosc82f2e12016-09-05 01:36:50 -0700709};
710
711TEST_F(RTCStatsCollectorTest, SingleCallback) {
712 rtc::scoped_refptr<const RTCStatsReport> result;
Steve Anton5b387312018-02-02 16:00:20 -0800713 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&result));
hbosc82f2e12016-09-05 01:36:50 -0700714 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
715}
716
717TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
Steve Anton5b387312018-02-02 16:00:20 -0800718 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
719 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
720 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
721 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700722 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
723 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
724 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
Steve Anton5b387312018-02-02 16:00:20 -0800725
hbosc82f2e12016-09-05 01:36:50 -0700726 EXPECT_EQ(a.get(), b.get());
727 EXPECT_EQ(b.get(), c.get());
728}
729
730TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700731 // Caching should ensure |a| and |b| are the same report.
Steve Anton5b387312018-02-02 16:00:20 -0800732 rtc::scoped_refptr<const RTCStatsReport> a = stats_->GetStatsReport();
733 rtc::scoped_refptr<const RTCStatsReport> b = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700734 EXPECT_EQ(a.get(), b.get());
735 // Invalidate cache by clearing it.
Steve Anton5b387312018-02-02 16:00:20 -0800736 stats_->stats_collector()->ClearCachedStatsReport();
737 rtc::scoped_refptr<const RTCStatsReport> c = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700738 EXPECT_NE(b.get(), c.get());
739 // Invalidate cache by advancing time.
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200740 fake_clock_.AdvanceTime(TimeDelta::ms(51));
Steve Anton5b387312018-02-02 16:00:20 -0800741 rtc::scoped_refptr<const RTCStatsReport> d = stats_->GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700742 EXPECT_TRUE(d);
743 EXPECT_NE(c.get(), d.get());
744}
745
hbosc82f2e12016-09-05 01:36:50 -0700746TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
Steve Anton5b387312018-02-02 16:00:20 -0800747 rtc::scoped_refptr<const RTCStatsReport> a, b, c;
748 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&a));
749 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&b));
hbosc82f2e12016-09-05 01:36:50 -0700750 // Cache is invalidated after 50 ms.
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200751 fake_clock_.AdvanceTime(TimeDelta::ms(51));
Steve Anton5b387312018-02-02 16:00:20 -0800752 stats_->stats_collector()->GetStatsReport(RTCStatsObtainer::Create(&c));
hbosc82f2e12016-09-05 01:36:50 -0700753 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
754 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
755 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
756 EXPECT_EQ(a.get(), b.get());
757 // The act of doing |AdvanceTime| processes all messages. If this was not the
758 // case we might not require |c| to be fresher than |b|.
759 EXPECT_NE(c.get(), b.get());
760}
761
hbos6ab97ce2016-10-03 14:16:56 -0700762TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
Steve Anton5b387312018-02-02 16:00:20 -0800763 const char kTransportName[] = "transport";
764
765 pc_->AddVoiceChannel("audio", kTransportName);
766
hbos6ab97ce2016-10-03 14:16:56 -0700767 std::unique_ptr<CertificateInfo> local_certinfo =
768 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200769 std::vector<std::string>({"(local) single certificate"}));
Steve Anton5b387312018-02-02 16:00:20 -0800770 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
771
hbos6ab97ce2016-10-03 14:16:56 -0700772 std::unique_ptr<CertificateInfo> remote_certinfo =
773 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200774 std::vector<std::string>({"(remote) single certificate"}));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800775 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 01:16:26 -0700776 kTransportName,
777 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce2016-10-03 14:16:56 -0700778
Steve Anton5b387312018-02-02 16:00:20 -0800779 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ab97ce2016-10-03 14:16:56 -0700780
hbos23368e12016-12-21 04:29:17 -0800781 ExpectReportContainsCertificateInfo(report, *local_certinfo);
782 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700783}
784
hbos0adb8282016-11-23 02:32:06 -0800785TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
hbos0adb8282016-11-23 02:32:06 -0800786 // Audio
787 cricket::VoiceMediaInfo voice_media_info;
788
789 RtpCodecParameters inbound_audio_codec;
790 inbound_audio_codec.payload_type = 1;
deadbeefe702b302017-02-04 12:09:01 -0800791 inbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
792 inbound_audio_codec.name = "opus";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100793 inbound_audio_codec.clock_rate = 1337;
hbos0adb8282016-11-23 02:32:06 -0800794 voice_media_info.receive_codecs.insert(
795 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
796
797 RtpCodecParameters outbound_audio_codec;
798 outbound_audio_codec.payload_type = 2;
deadbeefe702b302017-02-04 12:09:01 -0800799 outbound_audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
800 outbound_audio_codec.name = "isac";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100801 outbound_audio_codec.clock_rate = 1338;
hbos0adb8282016-11-23 02:32:06 -0800802 voice_media_info.send_codecs.insert(
803 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
804
Steve Anton57858b32018-02-15 15:19:50 -0800805 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800806 voice_media_channel->SetStats(voice_media_info);
hbos0adb8282016-11-23 02:32:06 -0800807
808 // Video
809 cricket::VideoMediaInfo video_media_info;
810
811 RtpCodecParameters inbound_video_codec;
812 inbound_video_codec.payload_type = 3;
deadbeefe702b302017-02-04 12:09:01 -0800813 inbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
814 inbound_video_codec.name = "H264";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100815 inbound_video_codec.clock_rate = 1339;
hbos0adb8282016-11-23 02:32:06 -0800816 video_media_info.receive_codecs.insert(
817 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
818
819 RtpCodecParameters outbound_video_codec;
820 outbound_video_codec.payload_type = 4;
deadbeefe702b302017-02-04 12:09:01 -0800821 outbound_video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
822 outbound_video_codec.name = "VP8";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +0100823 outbound_video_codec.clock_rate = 1340;
hbos0adb8282016-11-23 02:32:06 -0800824 video_media_info.send_codecs.insert(
825 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
826
Steve Anton57858b32018-02-15 15:19:50 -0800827 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -0800828 video_media_channel->SetStats(video_media_info);
hbos0adb8282016-11-23 02:32:06 -0800829
Steve Anton5b387312018-02-02 16:00:20 -0800830 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0adb8282016-11-23 02:32:06 -0800831
Steve Anton57858b32018-02-15 15:19:50 -0800832 RTCCodecStats expected_inbound_audio_codec("RTCCodec_AudioMid_Inbound_1",
833 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800834 expected_inbound_audio_codec.payload_type = 1;
hbos13f54b22017-02-28 06:56:04 -0800835 expected_inbound_audio_codec.mime_type = "audio/opus";
hbos0adb8282016-11-23 02:32:06 -0800836 expected_inbound_audio_codec.clock_rate = 1337;
837
Steve Anton57858b32018-02-15 15:19:50 -0800838 RTCCodecStats expected_outbound_audio_codec("RTCCodec_AudioMid_Outbound_2",
839 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800840 expected_outbound_audio_codec.payload_type = 2;
hbos13f54b22017-02-28 06:56:04 -0800841 expected_outbound_audio_codec.mime_type = "audio/isac";
hbos0adb8282016-11-23 02:32:06 -0800842 expected_outbound_audio_codec.clock_rate = 1338;
843
Steve Anton57858b32018-02-15 15:19:50 -0800844 RTCCodecStats expected_inbound_video_codec("RTCCodec_VideoMid_Inbound_3",
845 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800846 expected_inbound_video_codec.payload_type = 3;
hbos13f54b22017-02-28 06:56:04 -0800847 expected_inbound_video_codec.mime_type = "video/H264";
hbos0adb8282016-11-23 02:32:06 -0800848 expected_inbound_video_codec.clock_rate = 1339;
849
Steve Anton57858b32018-02-15 15:19:50 -0800850 RTCCodecStats expected_outbound_video_codec("RTCCodec_VideoMid_Outbound_4",
851 report->timestamp_us());
hbos0adb8282016-11-23 02:32:06 -0800852 expected_outbound_video_codec.payload_type = 4;
hbos13f54b22017-02-28 06:56:04 -0800853 expected_outbound_video_codec.mime_type = "video/VP8";
hbos0adb8282016-11-23 02:32:06 -0800854 expected_outbound_video_codec.clock_rate = 1340;
855
nissec8ee8822017-01-18 07:20:55 -0800856 ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id()));
Yves Gerey665174f2018-06-19 15:03:05 +0200857 EXPECT_EQ(
858 expected_inbound_audio_codec,
859 report->Get(expected_inbound_audio_codec.id())->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 02:32:06 -0800860
nissec8ee8822017-01-18 07:20:55 -0800861 ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800862 EXPECT_EQ(expected_outbound_audio_codec,
Yves Gerey665174f2018-06-19 15:03:05 +0200863 report->Get(expected_outbound_audio_codec.id())
864 ->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 02:32:06 -0800865
nissec8ee8822017-01-18 07:20:55 -0800866 ASSERT_TRUE(report->Get(expected_inbound_video_codec.id()));
Yves Gerey665174f2018-06-19 15:03:05 +0200867 EXPECT_EQ(
868 expected_inbound_video_codec,
869 report->Get(expected_inbound_video_codec.id())->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 02:32:06 -0800870
nissec8ee8822017-01-18 07:20:55 -0800871 ASSERT_TRUE(report->Get(expected_outbound_video_codec.id()));
hbos0adb8282016-11-23 02:32:06 -0800872 EXPECT_EQ(expected_outbound_video_codec,
Yves Gerey665174f2018-06-19 15:03:05 +0200873 report->Get(expected_outbound_video_codec.id())
874 ->cast_to<RTCCodecStats>());
hbos0adb8282016-11-23 02:32:06 -0800875}
876
hbos6ab97ce2016-10-03 14:16:56 -0700877TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
Steve Anton5b387312018-02-02 16:00:20 -0800878 const char kAudioTransport[] = "audio";
879 const char kVideoTransport[] = "video";
880
881 pc_->AddVoiceChannel("audio", kAudioTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700882 std::unique_ptr<CertificateInfo> audio_local_certinfo =
883 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200884 std::vector<std::string>({"(local) audio"}));
Steve Anton5b387312018-02-02 16:00:20 -0800885 pc_->SetLocalCertificate(kAudioTransport, audio_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700886 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
887 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200888 std::vector<std::string>({"(remote) audio"}));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800889 pc_->SetRemoteCertChain(
890 kAudioTransport,
Benjamin Wright6c6c9df2018-10-25 01:16:26 -0700891 audio_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce2016-10-03 14:16:56 -0700892
Steve Anton5b387312018-02-02 16:00:20 -0800893 pc_->AddVideoChannel("video", kVideoTransport);
hbos6ab97ce2016-10-03 14:16:56 -0700894 std::unique_ptr<CertificateInfo> video_local_certinfo =
895 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200896 std::vector<std::string>({"(local) video"}));
Steve Anton5b387312018-02-02 16:00:20 -0800897 pc_->SetLocalCertificate(kVideoTransport, video_local_certinfo->certificate);
hbos6ab97ce2016-10-03 14:16:56 -0700898 std::unique_ptr<CertificateInfo> video_remote_certinfo =
899 CreateFakeCertificateAndInfoFromDers(
Yves Gerey665174f2018-06-19 15:03:05 +0200900 std::vector<std::string>({"(remote) video"}));
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800901 pc_->SetRemoteCertChain(
902 kVideoTransport,
Benjamin Wright6c6c9df2018-10-25 01:16:26 -0700903 video_remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce2016-10-03 14:16:56 -0700904
Steve Anton5b387312018-02-02 16:00:20 -0800905 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800906 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo);
907 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo);
908 ExpectReportContainsCertificateInfo(report, *video_local_certinfo);
909 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700910}
911
912TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
Steve Anton5b387312018-02-02 16:00:20 -0800913 const char kTransportName[] = "transport";
914
915 pc_->AddVoiceChannel("audio", kTransportName);
916
hbos6ab97ce2016-10-03 14:16:56 -0700917 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800918 CreateFakeCertificateAndInfoFromDers(
919 {"(local) this", "(local) is", "(local) a", "(local) chain"});
920 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
921
hbos6ab97ce2016-10-03 14:16:56 -0700922 std::unique_ptr<CertificateInfo> remote_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -0800923 CreateFakeCertificateAndInfoFromDers({"(remote) this", "(remote) is",
924 "(remote) another",
925 "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800926 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 01:16:26 -0700927 kTransportName,
928 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos6ab97ce2016-10-03 14:16:56 -0700929
Steve Anton5b387312018-02-02 16:00:20 -0800930 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos23368e12016-12-21 04:29:17 -0800931 ExpectReportContainsCertificateInfo(report, *local_certinfo);
932 ExpectReportContainsCertificateInfo(report, *remote_certinfo);
hbos6ab97ce2016-10-03 14:16:56 -0700933}
934
hboscc555c52016-10-18 12:48:31 -0700935TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
Steve Anton5b387312018-02-02 16:00:20 -0800936 pc_->AddSctpDataChannel(new MockDataChannel(0, "MockDataChannel0",
937 DataChannelInterface::kConnecting,
938 "udp", 1, 2, 3, 4));
hbosdbb64d82016-12-21 01:57:46 -0800939 RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0);
940 expected_data_channel0.label = "MockDataChannel0";
941 expected_data_channel0.protocol = "udp";
942 expected_data_channel0.datachannelid = 0;
943 expected_data_channel0.state = "connecting";
944 expected_data_channel0.messages_sent = 1;
945 expected_data_channel0.bytes_sent = 2;
946 expected_data_channel0.messages_received = 3;
947 expected_data_channel0.bytes_received = 4;
948
Steve Anton5b387312018-02-02 16:00:20 -0800949 pc_->AddSctpDataChannel(new MockDataChannel(
Steve Antonbe5e2082018-01-24 15:29:17 -0800950 1, "MockDataChannel1", DataChannelInterface::kOpen, "tcp", 5, 6, 7, 8));
hbosdbb64d82016-12-21 01:57:46 -0800951 RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0);
952 expected_data_channel1.label = "MockDataChannel1";
953 expected_data_channel1.protocol = "tcp";
954 expected_data_channel1.datachannelid = 1;
955 expected_data_channel1.state = "open";
956 expected_data_channel1.messages_sent = 5;
957 expected_data_channel1.bytes_sent = 6;
958 expected_data_channel1.messages_received = 7;
959 expected_data_channel1.bytes_received = 8;
960
Steve Anton5b387312018-02-02 16:00:20 -0800961 pc_->AddSctpDataChannel(new MockDataChannel(2, "MockDataChannel2",
962 DataChannelInterface::kClosing,
963 "udp", 9, 10, 11, 12));
hbosdbb64d82016-12-21 01:57:46 -0800964 RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0);
965 expected_data_channel2.label = "MockDataChannel2";
966 expected_data_channel2.protocol = "udp";
967 expected_data_channel2.datachannelid = 2;
968 expected_data_channel2.state = "closing";
969 expected_data_channel2.messages_sent = 9;
970 expected_data_channel2.bytes_sent = 10;
971 expected_data_channel2.messages_received = 11;
972 expected_data_channel2.bytes_received = 12;
973
Steve Anton5b387312018-02-02 16:00:20 -0800974 pc_->AddSctpDataChannel(new MockDataChannel(3, "MockDataChannel3",
975 DataChannelInterface::kClosed,
976 "tcp", 13, 14, 15, 16));
hbosdbb64d82016-12-21 01:57:46 -0800977 RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0);
978 expected_data_channel3.label = "MockDataChannel3";
979 expected_data_channel3.protocol = "tcp";
980 expected_data_channel3.datachannelid = 3;
981 expected_data_channel3.state = "closed";
982 expected_data_channel3.messages_sent = 13;
983 expected_data_channel3.bytes_sent = 14;
984 expected_data_channel3.messages_received = 15;
985 expected_data_channel3.bytes_received = 16;
hboscc555c52016-10-18 12:48:31 -0700986
Steve Anton5b387312018-02-02 16:00:20 -0800987 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
988
hbosdbb64d82016-12-21 01:57:46 -0800989 ASSERT_TRUE(report->Get(expected_data_channel0.id()));
Yves Gerey665174f2018-06-19 15:03:05 +0200990 EXPECT_EQ(
991 expected_data_channel0,
992 report->Get(expected_data_channel0.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 01:57:46 -0800993 ASSERT_TRUE(report->Get(expected_data_channel1.id()));
Yves Gerey665174f2018-06-19 15:03:05 +0200994 EXPECT_EQ(
995 expected_data_channel1,
996 report->Get(expected_data_channel1.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 01:57:46 -0800997 ASSERT_TRUE(report->Get(expected_data_channel2.id()));
Yves Gerey665174f2018-06-19 15:03:05 +0200998 EXPECT_EQ(
999 expected_data_channel2,
1000 report->Get(expected_data_channel2.id())->cast_to<RTCDataChannelStats>());
hbosdbb64d82016-12-21 01:57:46 -08001001 ASSERT_TRUE(report->Get(expected_data_channel3.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001002 EXPECT_EQ(
1003 expected_data_channel3,
1004 report->Get(expected_data_channel3.id())->cast_to<RTCDataChannelStats>());
hboscc555c52016-10-18 12:48:31 -07001005}
1006
hbosab9f6e42016-10-07 02:18:47 -07001007TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
1008 // Candidates in the first transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -08001009 std::unique_ptr<cricket::Candidate> a_local_host =
1010 CreateFakeCandidate("1.2.3.4", 5, "a_local_host's protocol",
1011 rtc::ADAPTER_TYPE_VPN, cricket::LOCAL_PORT_TYPE, 0);
hbosc42ba322016-12-21 03:31:45 -08001012 RTCLocalIceCandidateStats expected_a_local_host(
1013 "RTCIceCandidate_" + a_local_host->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001014 expected_a_local_host.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -08001015 expected_a_local_host.network_type = "vpn";
hbosc42ba322016-12-21 03:31:45 -08001016 expected_a_local_host.ip = "1.2.3.4";
1017 expected_a_local_host.port = 5;
1018 expected_a_local_host.protocol = "a_local_host's protocol";
1019 expected_a_local_host.candidate_type = "host";
1020 expected_a_local_host.priority = 0;
hbosc3a2b7f2017-01-02 04:46:15 -08001021 EXPECT_FALSE(*expected_a_local_host.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001022
hbosab9f6e42016-10-07 02:18:47 -07001023 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001024 "6.7.8.9", 10, "remote_srflx's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1025 cricket::STUN_PORT_TYPE, 1);
hbosc42ba322016-12-21 03:31:45 -08001026 RTCRemoteIceCandidateStats expected_a_remote_srflx(
1027 "RTCIceCandidate_" + a_remote_srflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001028 expected_a_remote_srflx.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -08001029 expected_a_remote_srflx.ip = "6.7.8.9";
1030 expected_a_remote_srflx.port = 10;
1031 expected_a_remote_srflx.protocol = "remote_srflx's protocol";
1032 expected_a_remote_srflx.candidate_type = "srflx";
1033 expected_a_remote_srflx.priority = 1;
hbosd17a5a72017-01-02 08:09:59 -08001034 expected_a_remote_srflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001035 EXPECT_TRUE(*expected_a_remote_srflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001036
hbosab9f6e42016-10-07 02:18:47 -07001037 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001038 "11.12.13.14", 15, "a_local_prflx's protocol", rtc::ADAPTER_TYPE_CELLULAR,
1039 cricket::PRFLX_PORT_TYPE, 2);
hbosc42ba322016-12-21 03:31:45 -08001040 RTCLocalIceCandidateStats expected_a_local_prflx(
1041 "RTCIceCandidate_" + a_local_prflx->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001042 expected_a_local_prflx.transport_id = "RTCTransport_a_0";
Gary Liu37e489c2017-11-21 10:49:36 -08001043 expected_a_local_prflx.network_type = "cellular";
hbosc42ba322016-12-21 03:31:45 -08001044 expected_a_local_prflx.ip = "11.12.13.14";
1045 expected_a_local_prflx.port = 15;
1046 expected_a_local_prflx.protocol = "a_local_prflx's protocol";
1047 expected_a_local_prflx.candidate_type = "prflx";
1048 expected_a_local_prflx.priority = 2;
hbosd17a5a72017-01-02 08:09:59 -08001049 expected_a_local_prflx.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001050 EXPECT_FALSE(*expected_a_local_prflx.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001051
hbosab9f6e42016-10-07 02:18:47 -07001052 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001053 "16.17.18.19", 20, "a_remote_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1054 cricket::RELAY_PORT_TYPE, 3);
hbosc42ba322016-12-21 03:31:45 -08001055 RTCRemoteIceCandidateStats expected_a_remote_relay(
1056 "RTCIceCandidate_" + a_remote_relay->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001057 expected_a_remote_relay.transport_id = "RTCTransport_a_0";
hbosc42ba322016-12-21 03:31:45 -08001058 expected_a_remote_relay.ip = "16.17.18.19";
1059 expected_a_remote_relay.port = 20;
1060 expected_a_remote_relay.protocol = "a_remote_relay's protocol";
1061 expected_a_remote_relay.candidate_type = "relay";
1062 expected_a_remote_relay.priority = 3;
hbosd17a5a72017-01-02 08:09:59 -08001063 expected_a_remote_relay.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001064 EXPECT_TRUE(*expected_a_remote_relay.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001065
Philipp Hancke95513752018-09-27 14:40:08 +02001066 std::unique_ptr<cricket::Candidate> a_local_relay = CreateFakeCandidate(
1067 "16.17.18.19", 21, "a_local_relay's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1068 cricket::RELAY_PORT_TYPE, 1);
1069 a_local_relay->set_relay_protocol("tcp");
1070
1071 RTCRemoteIceCandidateStats expected_a_local_relay(
1072 "RTCIceCandidate_" + a_local_relay->id(), 0);
1073 expected_a_local_relay.transport_id = "RTCTransport_a_0";
1074 expected_a_local_relay.ip = "16.17.18.19";
1075 expected_a_local_relay.port = 21;
1076 expected_a_local_relay.protocol = "a_local_relay's protocol";
1077 expected_a_local_relay.relay_protocol = "tcp";
1078 expected_a_local_relay.candidate_type = "relay";
1079 expected_a_local_relay.priority = 1;
1080 expected_a_local_relay.deleted = false;
1081 EXPECT_TRUE(*expected_a_local_relay.is_remote);
1082
hbosab9f6e42016-10-07 02:18:47 -07001083 // Candidates in the second transport stats.
Gary Liu37e489c2017-11-21 10:49:36 -08001084 std::unique_ptr<cricket::Candidate> b_local =
1085 CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol",
1086 rtc::ADAPTER_TYPE_WIFI, cricket::LOCAL_PORT_TYPE, 42);
Yves Gerey665174f2018-06-19 15:03:05 +02001087 RTCLocalIceCandidateStats expected_b_local("RTCIceCandidate_" + b_local->id(),
1088 0);
hbosb4e426e2017-01-02 09:59:31 -08001089 expected_b_local.transport_id = "RTCTransport_b_0";
Gary Liu37e489c2017-11-21 10:49:36 -08001090 expected_b_local.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -08001091 expected_b_local.ip = "42.42.42.42";
1092 expected_b_local.port = 42;
1093 expected_b_local.protocol = "b_local's protocol";
1094 expected_b_local.candidate_type = "host";
1095 expected_b_local.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001096 expected_b_local.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001097 EXPECT_FALSE(*expected_b_local.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001098
hbosab9f6e42016-10-07 02:18:47 -07001099 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001100 "42.42.42.42", 42, "b_remote's protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1101 cricket::LOCAL_PORT_TYPE, 42);
hbosc42ba322016-12-21 03:31:45 -08001102 RTCRemoteIceCandidateStats expected_b_remote(
1103 "RTCIceCandidate_" + b_remote->id(), 0);
hbosb4e426e2017-01-02 09:59:31 -08001104 expected_b_remote.transport_id = "RTCTransport_b_0";
hbosc42ba322016-12-21 03:31:45 -08001105 expected_b_remote.ip = "42.42.42.42";
1106 expected_b_remote.port = 42;
1107 expected_b_remote.protocol = "b_remote's protocol";
1108 expected_b_remote.candidate_type = "host";
1109 expected_b_remote.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001110 expected_b_remote.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001111 EXPECT_TRUE(*expected_b_remote.is_remote);
hbosab9f6e42016-10-07 02:18:47 -07001112
Philipp Hancke95513752018-09-27 14:40:08 +02001113 // Add candidate pairs to connection.
hbosab9f6e42016-10-07 02:18:47 -07001114 cricket::TransportChannelStats a_transport_channel_stats;
1115 a_transport_channel_stats.connection_infos.push_back(
1116 cricket::ConnectionInfo());
1117 a_transport_channel_stats.connection_infos[0].local_candidate =
1118 *a_local_host.get();
1119 a_transport_channel_stats.connection_infos[0].remote_candidate =
1120 *a_remote_srflx.get();
1121 a_transport_channel_stats.connection_infos.push_back(
1122 cricket::ConnectionInfo());
1123 a_transport_channel_stats.connection_infos[1].local_candidate =
1124 *a_local_prflx.get();
1125 a_transport_channel_stats.connection_infos[1].remote_candidate =
1126 *a_remote_relay.get();
Philipp Hancke95513752018-09-27 14:40:08 +02001127 a_transport_channel_stats.connection_infos.push_back(
1128 cricket::ConnectionInfo());
1129 a_transport_channel_stats.connection_infos[2].local_candidate =
1130 *a_local_relay.get();
1131 a_transport_channel_stats.connection_infos[2].remote_candidate =
1132 *a_remote_relay.get();
Steve Anton5b387312018-02-02 16:00:20 -08001133
1134 pc_->AddVoiceChannel("audio", "a");
1135 pc_->SetTransportStats("a", a_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -07001136
1137 cricket::TransportChannelStats b_transport_channel_stats;
1138 b_transport_channel_stats.connection_infos.push_back(
1139 cricket::ConnectionInfo());
1140 b_transport_channel_stats.connection_infos[0].local_candidate =
1141 *b_local.get();
1142 b_transport_channel_stats.connection_infos[0].remote_candidate =
1143 *b_remote.get();
hbosab9f6e42016-10-07 02:18:47 -07001144
Steve Anton5b387312018-02-02 16:00:20 -08001145 pc_->AddVideoChannel("video", "b");
1146 pc_->SetTransportStats("b", b_transport_channel_stats);
hbosab9f6e42016-10-07 02:18:47 -07001147
Steve Anton5b387312018-02-02 16:00:20 -08001148 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbosc42ba322016-12-21 03:31:45 -08001149
hbosb4e426e2017-01-02 09:59:31 -08001150 ASSERT_TRUE(report->Get(expected_a_local_host.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001151 EXPECT_EQ(expected_a_local_host, report->Get(expected_a_local_host.id())
1152 ->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001153 ASSERT_TRUE(report->Get(expected_a_remote_srflx.id()));
hbosc42ba322016-12-21 03:31:45 -08001154 EXPECT_EQ(expected_a_remote_srflx,
Yves Gerey665174f2018-06-19 15:03:05 +02001155 report->Get(expected_a_remote_srflx.id())
1156 ->cast_to<RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001157 ASSERT_TRUE(report->Get(expected_a_local_prflx.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001158 EXPECT_EQ(expected_a_local_prflx, report->Get(expected_a_local_prflx.id())
1159 ->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001160 ASSERT_TRUE(report->Get(expected_a_remote_relay.id()));
hbosc42ba322016-12-21 03:31:45 -08001161 EXPECT_EQ(expected_a_remote_relay,
Yves Gerey665174f2018-06-19 15:03:05 +02001162 report->Get(expected_a_remote_relay.id())
1163 ->cast_to<RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001164 ASSERT_TRUE(report->Get(expected_b_local.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001165 EXPECT_EQ(
1166 expected_b_local,
1167 report->Get(expected_b_local.id())->cast_to<RTCLocalIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001168 ASSERT_TRUE(report->Get(expected_b_remote.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001169 EXPECT_EQ(expected_b_remote, report->Get(expected_b_remote.id())
1170 ->cast_to<RTCRemoteIceCandidateStats>());
hbosb4e426e2017-01-02 09:59:31 -08001171 EXPECT_TRUE(report->Get("RTCTransport_a_0"));
1172 EXPECT_TRUE(report->Get("RTCTransport_b_0"));
hbosab9f6e42016-10-07 02:18:47 -07001173}
1174
hbosc47a0c32016-10-11 14:54:49 -07001175TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
Steve Anton5b387312018-02-02 16:00:20 -08001176 const char kTransportName[] = "transport";
hbos338f78a2017-02-07 06:41:21 -08001177
Gary Liu37e489c2017-11-21 10:49:36 -08001178 std::unique_ptr<cricket::Candidate> local_candidate =
1179 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
1180 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -07001181 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
Gary Liu37e489c2017-11-21 10:49:36 -08001182 "42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_UNKNOWN,
1183 cricket::LOCAL_PORT_TYPE, 42);
hbosc47a0c32016-10-11 14:54:49 -07001184
hbosc47a0c32016-10-11 14:54:49 -07001185 cricket::ConnectionInfo connection_info;
hbos338f78a2017-02-07 06:41:21 -08001186 connection_info.best_connection = false;
hbosc47a0c32016-10-11 14:54:49 -07001187 connection_info.local_candidate = *local_candidate.get();
1188 connection_info.remote_candidate = *remote_candidate.get();
1189 connection_info.writable = true;
1190 connection_info.sent_total_bytes = 42;
1191 connection_info.recv_total_bytes = 1234;
hbosbf8d3e52017-02-28 06:34:47 -08001192 connection_info.total_round_trip_time_ms = 0;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001193 connection_info.current_round_trip_time_ms = absl::nullopt;
hbosd82f5122016-12-09 04:12:39 -08001194 connection_info.recv_ping_requests = 2020;
hbose448dd52016-12-12 01:22:53 -08001195 connection_info.sent_ping_requests_total = 2020;
1196 connection_info.sent_ping_requests_before_first_response = 2000;
hbosc47a0c32016-10-11 14:54:49 -07001197 connection_info.recv_ping_responses = 4321;
1198 connection_info.sent_ping_responses = 1000;
hbos06495bc2017-01-02 08:08:18 -08001199 connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS;
1200 connection_info.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -08001201 connection_info.nominated = false;
hbosc47a0c32016-10-11 14:54:49 -07001202
1203 cricket::TransportChannelStats transport_channel_stats;
hbos0583b282016-11-30 01:50:14 -08001204 transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
hbosc47a0c32016-10-11 14:54:49 -07001205 transport_channel_stats.connection_infos.push_back(connection_info);
hbosc47a0c32016-10-11 14:54:49 -07001206
Steve Anton5b387312018-02-02 16:00:20 -08001207 pc_->AddVideoChannel("video", kTransportName);
1208 pc_->SetTransportStats(kTransportName, transport_channel_stats);
hbosc47a0c32016-10-11 14:54:49 -07001209
Steve Anton5b387312018-02-02 16:00:20 -08001210 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -08001211
1212 RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" +
1213 local_candidate->id() + "_" +
1214 remote_candidate->id(),
1215 report->timestamp_us());
1216 expected_pair.transport_id =
1217 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 11:59:48 +02001218 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0583b282016-11-30 01:50:14 -08001219 expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id();
1220 expected_pair.remote_candidate_id =
1221 "RTCIceCandidate_" + remote_candidate->id();
hbos06495bc2017-01-02 08:08:18 -08001222 expected_pair.state = RTCStatsIceCandidatePairState::kInProgress;
1223 expected_pair.priority = 5555;
hbos92eaec62017-02-27 01:38:08 -08001224 expected_pair.nominated = false;
hbos0583b282016-11-30 01:50:14 -08001225 expected_pair.writable = true;
1226 expected_pair.bytes_sent = 42;
1227 expected_pair.bytes_received = 1234;
hbosbf8d3e52017-02-28 06:34:47 -08001228 expected_pair.total_round_trip_time = 0.0;
hbosd82f5122016-12-09 04:12:39 -08001229 expected_pair.requests_received = 2020;
hbose448dd52016-12-12 01:22:53 -08001230 expected_pair.requests_sent = 2000;
hbos0583b282016-11-30 01:50:14 -08001231 expected_pair.responses_received = 4321;
1232 expected_pair.responses_sent = 1000;
hbose448dd52016-12-12 01:22:53 -08001233 expected_pair.consent_requests_sent = (2020 - 2000);
hbosbf8d3e52017-02-28 06:34:47 -08001234 // |expected_pair.current_round_trip_time| should be undefined because the
1235 // current RTT is not set.
hbos338f78a2017-02-07 06:41:21 -08001236 // |expected_pair.available_[outgoing/incoming]_bitrate| should be undefined
1237 // because is is not the current pair.
hbos0583b282016-11-30 01:50:14 -08001238
hbosdbb64d82016-12-21 01:57:46 -08001239 ASSERT_TRUE(report->Get(expected_pair.id()));
hbos0583b282016-11-30 01:50:14 -08001240 EXPECT_EQ(
1241 expected_pair,
1242 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
hbosb4e426e2017-01-02 09:59:31 -08001243 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
hbos0583b282016-11-30 01:50:14 -08001244
hbos92eaec62017-02-27 01:38:08 -08001245 // Set nominated and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001246 transport_channel_stats.connection_infos[0].nominated = true;
1247 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1248 report = stats_->GetFreshStatsReport();
hbos92eaec62017-02-27 01:38:08 -08001249 expected_pair.nominated = true;
1250 ASSERT_TRUE(report->Get(expected_pair.id()));
1251 EXPECT_EQ(
1252 expected_pair,
1253 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1254 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1255
hbosbf8d3e52017-02-28 06:34:47 -08001256 // Set round trip times and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001257 transport_channel_stats.connection_infos[0].total_round_trip_time_ms = 7331;
1258 transport_channel_stats.connection_infos[0].current_round_trip_time_ms = 1337;
1259 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1260 report = stats_->GetFreshStatsReport();
hbosbf8d3e52017-02-28 06:34:47 -08001261 expected_pair.total_round_trip_time = 7.331;
1262 expected_pair.current_round_trip_time = 1.337;
1263 ASSERT_TRUE(report->Get(expected_pair.id()));
1264 EXPECT_EQ(
1265 expected_pair,
1266 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1267 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1268
hbos338f78a2017-02-07 06:41:21 -08001269 // Make pair the current pair, clear bandwidth and "GetStats" again.
Steve Anton5b387312018-02-02 16:00:20 -08001270 transport_channel_stats.connection_infos[0].best_connection = true;
1271 pc_->SetTransportStats(kTransportName, transport_channel_stats);
1272 report = stats_->GetFreshStatsReport();
hbos338f78a2017-02-07 06:41:21 -08001273 // |expected_pair.available_[outgoing/incoming]_bitrate| should still be
1274 // undefined because bandwidth is not set.
1275 ASSERT_TRUE(report->Get(expected_pair.id()));
1276 EXPECT_EQ(
1277 expected_pair,
1278 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1279 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1280
1281 // Set bandwidth and "GetStats" again.
stefanf79ade12017-06-02 06:44:03 -07001282 webrtc::Call::Stats call_stats;
1283 const int kSendBandwidth = 888;
1284 call_stats.send_bandwidth_bps = kSendBandwidth;
1285 const int kRecvBandwidth = 999;
1286 call_stats.recv_bandwidth_bps = kRecvBandwidth;
Steve Anton5b387312018-02-02 16:00:20 -08001287 pc_->SetCallStats(call_stats);
1288 report = stats_->GetFreshStatsReport();
stefanf79ade12017-06-02 06:44:03 -07001289 expected_pair.available_outgoing_bitrate = kSendBandwidth;
1290 expected_pair.available_incoming_bitrate = kRecvBandwidth;
hbos338f78a2017-02-07 06:41:21 -08001291 ASSERT_TRUE(report->Get(expected_pair.id()));
1292 EXPECT_EQ(
1293 expected_pair,
1294 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>());
1295 EXPECT_TRUE(report->Get(*expected_pair.transport_id));
1296
hbosc42ba322016-12-21 03:31:45 -08001297 RTCLocalIceCandidateStats expected_local_candidate(
1298 *expected_pair.local_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001299 expected_local_candidate.transport_id = *expected_pair.transport_id;
Gary Liu37e489c2017-11-21 10:49:36 -08001300 expected_local_candidate.network_type = "wifi";
hbosc42ba322016-12-21 03:31:45 -08001301 expected_local_candidate.ip = "42.42.42.42";
1302 expected_local_candidate.port = 42;
1303 expected_local_candidate.protocol = "protocol";
1304 expected_local_candidate.candidate_type = "host";
1305 expected_local_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001306 expected_local_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001307 EXPECT_FALSE(*expected_local_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001308 ASSERT_TRUE(report->Get(expected_local_candidate.id()));
1309 EXPECT_EQ(expected_local_candidate,
Yves Gerey665174f2018-06-19 15:03:05 +02001310 report->Get(expected_local_candidate.id())
1311 ->cast_to<RTCLocalIceCandidateStats>());
hbosc42ba322016-12-21 03:31:45 -08001312
1313 RTCRemoteIceCandidateStats expected_remote_candidate(
1314 *expected_pair.remote_candidate_id, report->timestamp_us());
hbosb4e426e2017-01-02 09:59:31 -08001315 expected_remote_candidate.transport_id = *expected_pair.transport_id;
hbosc42ba322016-12-21 03:31:45 -08001316 expected_remote_candidate.ip = "42.42.42.42";
1317 expected_remote_candidate.port = 42;
1318 expected_remote_candidate.protocol = "protocol";
1319 expected_remote_candidate.candidate_type = "host";
1320 expected_remote_candidate.priority = 42;
hbosd17a5a72017-01-02 08:09:59 -08001321 expected_remote_candidate.deleted = false;
hbosc3a2b7f2017-01-02 04:46:15 -08001322 EXPECT_TRUE(*expected_remote_candidate.is_remote);
hbosc42ba322016-12-21 03:31:45 -08001323 ASSERT_TRUE(report->Get(expected_remote_candidate.id()));
1324 EXPECT_EQ(expected_remote_candidate,
Yves Gerey665174f2018-06-19 15:03:05 +02001325 report->Get(expected_remote_candidate.id())
1326 ->cast_to<RTCRemoteIceCandidateStats>());
hbosc47a0c32016-10-11 14:54:49 -07001327}
1328
hbosd565b732016-08-30 14:04:35 -07001329TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosd565b732016-08-30 14:04:35 -07001330 {
Steve Anton5b387312018-02-02 16:00:20 -08001331 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001332 RTCPeerConnectionStats expected("RTCPeerConnection",
1333 report->timestamp_us());
1334 expected.data_channels_opened = 0;
1335 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001336 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 15:03:05 +02001337 EXPECT_EQ(
1338 expected,
1339 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001340 }
1341
hbos82ebe022016-11-14 01:41:09 -08001342 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create(
1343 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001344 pc_->SignalDataChannelCreated()(dummy_channel_a.get());
hbos82ebe022016-11-14 01:41:09 -08001345 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create(
1346 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit());
Steve Anton5b387312018-02-02 16:00:20 -08001347 pc_->SignalDataChannelCreated()(dummy_channel_b.get());
hbosd565b732016-08-30 14:04:35 -07001348
hbos82ebe022016-11-14 01:41:09 -08001349 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1350 // Closing a channel that is not opened should not affect the counts.
1351 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1352
hbosd565b732016-08-30 14:04:35 -07001353 {
Steve Anton5b387312018-02-02 16:00:20 -08001354 rtc::scoped_refptr<const RTCStatsReport> report =
1355 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001356 RTCPeerConnectionStats expected("RTCPeerConnection",
1357 report->timestamp_us());
1358 expected.data_channels_opened = 1;
1359 expected.data_channels_closed = 0;
hbosdbb64d82016-12-21 01:57:46 -08001360 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 15:03:05 +02001361 EXPECT_EQ(
1362 expected,
1363 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos82ebe022016-11-14 01:41:09 -08001364 }
1365
1366 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1367 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1368
1369 {
Steve Anton5b387312018-02-02 16:00:20 -08001370 rtc::scoped_refptr<const RTCStatsReport> report =
1371 stats_->GetFreshStatsReport();
hbos82ebe022016-11-14 01:41:09 -08001372 RTCPeerConnectionStats expected("RTCPeerConnection",
1373 report->timestamp_us());
1374 expected.data_channels_opened = 2;
1375 expected.data_channels_closed = 1;
hbosdbb64d82016-12-21 01:57:46 -08001376 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 15:03:05 +02001377 EXPECT_EQ(
1378 expected,
1379 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001380 }
hbos5bf9def2017-03-20 03:14:14 -07001381
1382 // Re-opening a data channel (or opening a new data channel that is re-using
1383 // the same address in memory) should increase the opened count.
1384 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1385
1386 {
Steve Anton5b387312018-02-02 16:00:20 -08001387 rtc::scoped_refptr<const RTCStatsReport> report =
1388 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001389 RTCPeerConnectionStats expected("RTCPeerConnection",
1390 report->timestamp_us());
1391 expected.data_channels_opened = 3;
1392 expected.data_channels_closed = 1;
1393 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 15:03:05 +02001394 EXPECT_EQ(
1395 expected,
1396 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos5bf9def2017-03-20 03:14:14 -07001397 }
1398
1399 dummy_channel_a->SignalClosed(dummy_channel_a.get());
1400 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1401
1402 {
Steve Anton5b387312018-02-02 16:00:20 -08001403 rtc::scoped_refptr<const RTCStatsReport> report =
1404 stats_->GetFreshStatsReport();
hbos5bf9def2017-03-20 03:14:14 -07001405 RTCPeerConnectionStats expected("RTCPeerConnection",
1406 report->timestamp_us());
1407 expected.data_channels_opened = 3;
1408 expected.data_channels_closed = 3;
1409 ASSERT_TRUE(report->Get("RTCPeerConnection"));
Yves Gerey665174f2018-06-19 15:03:05 +02001410 EXPECT_EQ(
1411 expected,
1412 report->Get("RTCPeerConnection")->cast_to<RTCPeerConnectionStats>());
hbos5bf9def2017-03-20 03:14:14 -07001413 }
hbosd565b732016-08-30 14:04:35 -07001414}
1415
hbos09bc1282016-11-08 06:29:22 -08001416TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001417 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
hbos09bc1282016-11-08 06:29:22 -08001418 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001419 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001420 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001421
1422 // Local audio track
hbos9e302742017-01-20 02:47:10 -08001423 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track =
1424 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID",
1425 MediaStreamTrackInterface::kEnded);
Yves Gerey665174f2018-06-19 15:03:05 +02001426 local_stream->AddTrack(
1427 static_cast<AudioTrackInterface*>(local_audio_track.get()));
hbos9e302742017-01-20 02:47:10 -08001428
1429 cricket::VoiceSenderInfo voice_sender_info_ssrc1;
1430 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1431 voice_sender_info_ssrc1.local_stats[0].ssrc = 1;
1432 voice_sender_info_ssrc1.audio_level = 32767;
zsteine76bd3a2017-07-14 12:17:49 -07001433 voice_sender_info_ssrc1.total_input_energy = 0.25;
1434 voice_sender_info_ssrc1.total_input_duration = 0.5;
Ivo Creusen56d46092017-11-24 17:29:59 +01001435 voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
1436 voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
hbos9e302742017-01-20 02:47:10 -08001437
Steve Anton5b387312018-02-02 16:00:20 -08001438 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001439 {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001440 {}, {}, {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001441
Steve Anton5b387312018-02-02 16:00:20 -08001442 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001443
1444 RTCMediaStreamStats expected_local_stream(
1445 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001446 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001447 expected_local_stream.track_ids = {
1448 IdForType<RTCMediaStreamTrackStats>(report)};
1449 ASSERT_TRUE(report->Get(expected_local_stream.id()))
1450 << "Did not find " << expected_local_stream.id() << " in "
1451 << report->ToJson();
1452 EXPECT_EQ(
1453 expected_local_stream,
1454 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1455
1456 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
1457 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1458 RTCMediaStreamTrackKind::kAudio);
1459 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
Henrik Boström646fda02019-05-22 15:49:42 +02001460 expected_local_audio_track_ssrc1.media_source_id =
1461 "RTCAudioSource_11"; // Attachment ID = SSRC + 10
Harald Alvestranda3dab842018-01-14 09:18:58 +01001462 expected_local_audio_track_ssrc1.remote_source = false;
1463 expected_local_audio_track_ssrc1.ended = true;
1464 expected_local_audio_track_ssrc1.detached = false;
1465 expected_local_audio_track_ssrc1.audio_level = 1.0;
1466 expected_local_audio_track_ssrc1.total_audio_energy = 0.25;
1467 expected_local_audio_track_ssrc1.total_samples_duration = 0.5;
1468 expected_local_audio_track_ssrc1.echo_return_loss = 42.0;
1469 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0;
1470 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id()))
1471 << "Did not find " << expected_local_audio_track_ssrc1.id() << " in "
1472 << report->ToJson();
1473 EXPECT_EQ(expected_local_audio_track_ssrc1,
1474 report->Get(expected_local_audio_track_ssrc1.id())
1475 ->cast_to<RTCMediaStreamTrackStats>());
1476}
1477
1478TEST_F(RTCStatsCollectorTest,
1479 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001480 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001481 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001482 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001483
hbos09bc1282016-11-08 06:29:22 -08001484 // Remote audio track
hbos9e302742017-01-20 02:47:10 -08001485 rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
1486 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
1487 MediaStreamTrackInterface::kLive);
Yves Gerey665174f2018-06-19 15:03:05 +02001488 remote_stream->AddTrack(
1489 static_cast<AudioTrackInterface*>(remote_audio_track.get()));
hbos9e302742017-01-20 02:47:10 -08001490
1491 cricket::VoiceReceiverInfo voice_receiver_info;
1492 voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo());
1493 voice_receiver_info.local_stats[0].ssrc = 3;
1494 voice_receiver_info.audio_level = 16383;
zsteine76bd3a2017-07-14 12:17:49 -07001495 voice_receiver_info.total_output_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001496 voice_receiver_info.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001497 voice_receiver_info.total_output_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001498 voice_receiver_info.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001499 voice_receiver_info.concealment_events = 12;
Ivo Creusen8d8ffdb2019-04-30 09:45:21 +02001500 voice_receiver_info.inserted_samples_for_deceleration = 987;
1501 voice_receiver_info.removed_samples_for_acceleration = 876;
1502 voice_receiver_info.silent_concealed_samples = 765;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001503 voice_receiver_info.jitter_buffer_delay_seconds = 3456;
Chen Xing0acffb52019-01-15 15:46:29 +01001504 voice_receiver_info.jitter_buffer_emitted_count = 13;
Ruslan Burakov8af88962018-11-22 17:21:10 +01001505 voice_receiver_info.jitter_buffer_flushes = 7;
Jakob Ivarsson352ce5c2018-11-27 12:52:16 +01001506 voice_receiver_info.delayed_packet_outage_samples = 15;
Jakob Ivarsson232b3fd2019-03-06 09:18:40 +01001507 voice_receiver_info.relative_packet_arrival_delay_seconds = 16;
Henrik Lundin44125fa2019-04-29 17:00:46 +02001508 voice_receiver_info.interruption_count = 7788;
1509 voice_receiver_info.total_interruption_duration_ms = 778899;
hbos9e302742017-01-20 02:47:10 -08001510
Steve Anton5b387312018-02-02 16:00:20 -08001511 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001512 {}, {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {},
1513 {}, {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001514
Steve Anton5b387312018-02-02 16:00:20 -08001515 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001516
hbos09bc1282016-11-08 06:29:22 -08001517 RTCMediaStreamStats expected_remote_stream(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001518 IdForType<RTCMediaStreamStats>(report), report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001519 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001520 expected_remote_stream.track_ids =
1521 std::vector<std::string>({IdForType<RTCMediaStreamTrackStats>(report)});
1522 ASSERT_TRUE(report->Get(expected_remote_stream.id()))
1523 << "Did not find " << expected_remote_stream.id() << " in "
1524 << report->ToJson();
Yves Gerey665174f2018-06-19 15:03:05 +02001525 EXPECT_EQ(
1526 expected_remote_stream,
1527 report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
hbos09bc1282016-11-08 06:29:22 -08001528
hbos09bc1282016-11-08 06:29:22 -08001529 RTCMediaStreamTrackStats expected_remote_audio_track(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001530 IdForType<RTCMediaStreamTrackStats>(report), report->timestamp_us(),
1531 RTCMediaStreamTrackKind::kAudio);
hbos09bc1282016-11-08 06:29:22 -08001532 expected_remote_audio_track.track_identifier = remote_audio_track->id();
Henrik Boström646fda02019-05-22 15:49:42 +02001533 // |expected_remote_audio_track.media_source_id| should be undefined
1534 // because the track is remote.
hbos09bc1282016-11-08 06:29:22 -08001535 expected_remote_audio_track.remote_source = true;
1536 expected_remote_audio_track.ended = false;
1537 expected_remote_audio_track.detached = false;
hbos9e302742017-01-20 02:47:10 -08001538 expected_remote_audio_track.audio_level = 16383.0 / 32767.0;
zsteine76bd3a2017-07-14 12:17:49 -07001539 expected_remote_audio_track.total_audio_energy = 0.125;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001540 expected_remote_audio_track.total_samples_received = 4567;
zsteine76bd3a2017-07-14 12:17:49 -07001541 expected_remote_audio_track.total_samples_duration = 0.25;
Steve Anton2dbc69f2017-08-24 17:15:13 -07001542 expected_remote_audio_track.concealed_samples = 123;
Gustaf Ullberg9a2e9062017-09-18 09:28:20 +02001543 expected_remote_audio_track.concealment_events = 12;
Ivo Creusen8d8ffdb2019-04-30 09:45:21 +02001544 expected_remote_audio_track.inserted_samples_for_deceleration = 987;
1545 expected_remote_audio_track.removed_samples_for_acceleration = 876;
1546 expected_remote_audio_track.silent_concealed_samples = 765;
Gustaf Ullbergb0a02072017-10-02 12:00:34 +02001547 expected_remote_audio_track.jitter_buffer_delay = 3456;
Chen Xing0acffb52019-01-15 15:46:29 +01001548 expected_remote_audio_track.jitter_buffer_emitted_count = 13;
Ruslan Burakov8af88962018-11-22 17:21:10 +01001549 expected_remote_audio_track.jitter_buffer_flushes = 7;
Jakob Ivarsson352ce5c2018-11-27 12:52:16 +01001550 expected_remote_audio_track.delayed_packet_outage_samples = 15;
Jakob Ivarsson232b3fd2019-03-06 09:18:40 +01001551 expected_remote_audio_track.relative_packet_arrival_delay = 16;
Henrik Lundin44125fa2019-04-29 17:00:46 +02001552 expected_remote_audio_track.interruption_count = 7788;
1553 expected_remote_audio_track.total_interruption_duration = 778.899;
hbosdbb64d82016-12-21 01:57:46 -08001554 ASSERT_TRUE(report->Get(expected_remote_audio_track.id()));
hbos09bc1282016-11-08 06:29:22 -08001555 EXPECT_EQ(expected_remote_audio_track,
Yves Gerey665174f2018-06-19 15:03:05 +02001556 report->Get(expected_remote_audio_track.id())
1557 ->cast_to<RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 06:29:22 -08001558}
1559
1560TEST_F(RTCStatsCollectorTest,
Harald Alvestranda3dab842018-01-14 09:18:58 +01001561 CollectLocalRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
hbos09bc1282016-11-08 06:29:22 -08001562 rtc::scoped_refptr<MediaStream> local_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001563 MediaStream::Create("LocalStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001564 pc_->mutable_local_streams()->AddStream(local_stream);
hbos09bc1282016-11-08 06:29:22 -08001565
1566 // Local video track
hbos9e302742017-01-20 02:47:10 -08001567 rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track =
1568 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID",
1569 MediaStreamTrackInterface::kLive);
Yves Gerey665174f2018-06-19 15:03:05 +02001570 local_stream->AddTrack(
1571 static_cast<VideoTrackInterface*>(local_video_track.get()));
hbos09bc1282016-11-08 06:29:22 -08001572
hbos9e302742017-01-20 02:47:10 -08001573 cricket::VideoSenderInfo video_sender_info_ssrc1;
1574 video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo());
1575 video_sender_info_ssrc1.local_stats[0].ssrc = 1;
1576 video_sender_info_ssrc1.send_frame_width = 1234;
1577 video_sender_info_ssrc1.send_frame_height = 4321;
hbosfefe0762017-01-20 06:14:25 -08001578 video_sender_info_ssrc1.frames_encoded = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001579 video_sender_info_ssrc1.huge_frames_sent = 1;
hbos9e302742017-01-20 02:47:10 -08001580
Steve Anton5b387312018-02-02 16:00:20 -08001581 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001582 {}, {},
1583 {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)}, {},
Seth Hampson13b8bad2018-03-13 16:05:28 -07001584 {local_stream->id()}, {});
Harald Alvestranda3dab842018-01-14 09:18:58 +01001585
Steve Anton5b387312018-02-02 16:00:20 -08001586 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001587
1588 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001589 ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001590 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001591 ASSERT_EQ(1U, stats_of_track_type.size())
Harald Alvestranda3dab842018-01-14 09:18:58 +01001592 << "Wrong number of tracks in " << report->ToJson();
1593
1594 RTCMediaStreamStats expected_local_stream(stats_of_my_type[0]->id(),
1595 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001596 expected_local_stream.stream_identifier = local_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001597 expected_local_stream.track_ids =
1598 std::vector<std::string>({stats_of_track_type[0]->id()});
1599 ASSERT_TRUE(report->Get(expected_local_stream.id()));
1600 EXPECT_EQ(
1601 expected_local_stream,
1602 report->Get(expected_local_stream.id())->cast_to<RTCMediaStreamStats>());
1603
1604 RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
1605 stats_of_track_type[0]->id(), report->timestamp_us(),
1606 RTCMediaStreamTrackKind::kVideo);
1607 expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
Henrik Boström646fda02019-05-22 15:49:42 +02001608 expected_local_video_track_ssrc1.media_source_id =
1609 "RTCVideoSource_11"; // Attachment ID = SSRC + 10
Harald Alvestranda3dab842018-01-14 09:18:58 +01001610 expected_local_video_track_ssrc1.remote_source = false;
1611 expected_local_video_track_ssrc1.ended = false;
1612 expected_local_video_track_ssrc1.detached = false;
1613 expected_local_video_track_ssrc1.frame_width = 1234;
1614 expected_local_video_track_ssrc1.frame_height = 4321;
1615 expected_local_video_track_ssrc1.frames_sent = 11;
Ilya Nikolaevskiy70473fc2018-02-28 16:35:03 +01001616 expected_local_video_track_ssrc1.huge_frames_sent = 1;
Harald Alvestranda3dab842018-01-14 09:18:58 +01001617 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id()));
1618 EXPECT_EQ(expected_local_video_track_ssrc1,
1619 report->Get(expected_local_video_track_ssrc1.id())
1620 ->cast_to<RTCMediaStreamTrackStats>());
1621}
1622
1623TEST_F(RTCStatsCollectorTest,
1624 CollectRemoteRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
Harald Alvestranda3dab842018-01-14 09:18:58 +01001625 rtc::scoped_refptr<MediaStream> remote_stream =
Seth Hampson845e8782018-03-02 11:34:10 -08001626 MediaStream::Create("RemoteStreamId");
Steve Anton5b387312018-02-02 16:00:20 -08001627 pc_->mutable_remote_streams()->AddStream(remote_stream);
Harald Alvestranda3dab842018-01-14 09:18:58 +01001628
hbos9e302742017-01-20 02:47:10 -08001629 // Remote video track with values
1630 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
1631 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
1632 MediaStreamTrackInterface::kEnded);
Yves Gerey665174f2018-06-19 15:03:05 +02001633 remote_stream->AddTrack(
1634 static_cast<VideoTrackInterface*>(remote_video_track_ssrc3.get()));
hbos9e302742017-01-20 02:47:10 -08001635
1636 cricket::VideoReceiverInfo video_receiver_info_ssrc3;
1637 video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo());
1638 video_receiver_info_ssrc3.local_stats[0].ssrc = 3;
1639 video_receiver_info_ssrc3.frame_width = 6789;
1640 video_receiver_info_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001641 video_receiver_info_ssrc3.frames_received = 1000;
1642 video_receiver_info_ssrc3.frames_decoded = 995;
1643 video_receiver_info_ssrc3.frames_rendered = 990;
Sergey Silkin02371062019-01-31 16:45:42 +01001644 video_receiver_info_ssrc3.freeze_count = 3;
1645 video_receiver_info_ssrc3.pause_count = 2;
1646 video_receiver_info_ssrc3.total_freezes_duration_ms = 1000;
1647 video_receiver_info_ssrc3.total_pauses_duration_ms = 10000;
1648 video_receiver_info_ssrc3.total_frames_duration_ms = 15000;
1649 video_receiver_info_ssrc3.sum_squared_frame_durations = 1.5;
hbos9e302742017-01-20 02:47:10 -08001650
Steve Anton5b387312018-02-02 16:00:20 -08001651 stats_->CreateMockRtpSendersReceiversAndChannels(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001652 {}, {}, {},
Harald Alvestrandc72af932018-01-11 17:18:19 +01001653 {std::make_pair(remote_video_track_ssrc3.get(),
Harald Alvestranda3dab842018-01-14 09:18:58 +01001654 video_receiver_info_ssrc3)},
1655 {}, {remote_stream});
hbos09bc1282016-11-08 06:29:22 -08001656
Steve Anton5b387312018-02-02 16:00:20 -08001657 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos09bc1282016-11-08 06:29:22 -08001658
Harald Alvestranda3dab842018-01-14 09:18:58 +01001659 auto stats_of_my_type = report->GetStatsOfType<RTCMediaStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001660 ASSERT_EQ(1U, stats_of_my_type.size()) << "No stream in " << report->ToJson();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001661 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001662 ASSERT_EQ(1U, stats_of_track_type.size())
Harald Alvestranda3dab842018-01-14 09:18:58 +01001663 << "Wrong number of tracks in " << report->ToJson();
1664 ASSERT_TRUE(*(stats_of_track_type[0]->remote_source));
hbos09bc1282016-11-08 06:29:22 -08001665
Harald Alvestranda3dab842018-01-14 09:18:58 +01001666 RTCMediaStreamStats expected_remote_stream(stats_of_my_type[0]->id(),
1667 report->timestamp_us());
Seth Hampson13b8bad2018-03-13 16:05:28 -07001668 expected_remote_stream.stream_identifier = remote_stream->id();
Harald Alvestranda3dab842018-01-14 09:18:58 +01001669 expected_remote_stream.track_ids =
1670 std::vector<std::string>({stats_of_track_type[0]->id()});
hbosdbb64d82016-12-21 01:57:46 -08001671 ASSERT_TRUE(report->Get(expected_remote_stream.id()));
Yves Gerey665174f2018-06-19 15:03:05 +02001672 EXPECT_EQ(
1673 expected_remote_stream,
1674 report->Get(expected_remote_stream.id())->cast_to<RTCMediaStreamStats>());
hbos09bc1282016-11-08 06:29:22 -08001675
hbos9e302742017-01-20 02:47:10 -08001676 RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
Harald Alvestranda3dab842018-01-14 09:18:58 +01001677 stats_of_track_type[0]->id(), report->timestamp_us(),
1678 RTCMediaStreamTrackKind::kVideo);
hbos9e302742017-01-20 02:47:10 -08001679 expected_remote_video_track_ssrc3.track_identifier =
1680 remote_video_track_ssrc3->id();
Henrik Boström646fda02019-05-22 15:49:42 +02001681 // |expected_remote_video_track_ssrc3.media_source_id| should be undefined
1682 // because the track is remote.
hbos9e302742017-01-20 02:47:10 -08001683 expected_remote_video_track_ssrc3.remote_source = true;
1684 expected_remote_video_track_ssrc3.ended = true;
1685 expected_remote_video_track_ssrc3.detached = false;
1686 expected_remote_video_track_ssrc3.frame_width = 6789;
1687 expected_remote_video_track_ssrc3.frame_height = 9876;
hbos50cfe1f2017-01-23 07:21:55 -08001688 expected_remote_video_track_ssrc3.frames_received = 1000;
1689 expected_remote_video_track_ssrc3.frames_decoded = 995;
1690 expected_remote_video_track_ssrc3.frames_dropped = 1000 - 990;
Sergey Silkin02371062019-01-31 16:45:42 +01001691 expected_remote_video_track_ssrc3.freeze_count = 3;
1692 expected_remote_video_track_ssrc3.pause_count = 2;
1693 expected_remote_video_track_ssrc3.total_freezes_duration = 1;
1694 expected_remote_video_track_ssrc3.total_pauses_duration = 10;
1695 expected_remote_video_track_ssrc3.total_frames_duration = 15;
1696 expected_remote_video_track_ssrc3.sum_squared_frame_durations = 1.5;
1697
hbos9e302742017-01-20 02:47:10 -08001698 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id()));
1699 EXPECT_EQ(expected_remote_video_track_ssrc3,
Yves Gerey665174f2018-06-19 15:03:05 +02001700 report->Get(expected_remote_video_track_ssrc3.id())
1701 ->cast_to<RTCMediaStreamTrackStats>());
hbos09bc1282016-11-08 06:29:22 -08001702}
1703
hboseeafe942016-11-01 03:00:17 -07001704TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
hboseeafe942016-11-01 03:00:17 -07001705 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001706
hboseeafe942016-11-01 03:00:17 -07001707 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1708 voice_media_info.receivers[0].local_stats.push_back(
1709 cricket::SsrcReceiverInfo());
1710 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001711 voice_media_info.receivers[0].packets_lost = -1; // Signed per RFC3550
hboseeafe942016-11-01 03:00:17 -07001712 voice_media_info.receivers[0].packets_rcvd = 2;
Ivo Creusen8d8ffdb2019-04-30 09:45:21 +02001713 voice_media_info.receivers[0].fec_packets_discarded = 5566;
1714 voice_media_info.receivers[0].fec_packets_received = 6677;
hboseeafe942016-11-01 03:00:17 -07001715 voice_media_info.receivers[0].bytes_rcvd = 3;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001716 voice_media_info.receivers[0].codec_payload_type = 42;
hboseeafe942016-11-01 03:00:17 -07001717 voice_media_info.receivers[0].jitter_ms = 4500;
1718 voice_media_info.receivers[0].fraction_lost = 5.5f;
Henrik Boström01738c62019-04-15 17:32:00 +02001719 voice_media_info.receivers[0].last_packet_received_timestamp_ms =
1720 absl::nullopt;
hbos0adb8282016-11-23 02:32:06 -08001721
1722 RtpCodecParameters codec_parameters;
1723 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001724 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1725 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001726 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001727 voice_media_info.receive_codecs.insert(
1728 std::make_pair(codec_parameters.payload_type, codec_parameters));
1729
Steve Anton57858b32018-02-15 15:19:50 -08001730 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001731 voice_media_channel->SetStats(voice_media_info);
Henrik Boström5b3541f2018-03-19 13:52:56 +01001732 stats_->SetupRemoteTrackAndReceiver(
1733 cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 03:00:17 -07001734
Steve Anton5b387312018-02-02 16:00:20 -08001735 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001736
Harald Alvestranda3dab842018-01-14 09:18:58 +01001737 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001738 ASSERT_EQ(1U, stats_of_track_type.size());
Harald Alvestranda3dab842018-01-14 09:18:58 +01001739
Yves Gerey665174f2018-06-19 15:03:05 +02001740 RTCInboundRTPStreamStats expected_audio("RTCInboundRTPAudioStream_1",
1741 report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001742 expected_audio.ssrc = 1;
hboseeafe942016-11-01 03:00:17 -07001743 expected_audio.is_remote = false;
1744 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 14:55:03 +02001745 expected_audio.kind = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001746 expected_audio.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001747 expected_audio.transport_id = "RTCTransport_TransportName_1";
1748 expected_audio.codec_id = "RTCCodec_AudioMid_Inbound_42";
hboseeafe942016-11-01 03:00:17 -07001749 expected_audio.packets_received = 2;
Ivo Creusen8d8ffdb2019-04-30 09:45:21 +02001750 expected_audio.fec_packets_discarded = 5566;
1751 expected_audio.fec_packets_received = 6677;
hboseeafe942016-11-01 03:00:17 -07001752 expected_audio.bytes_received = 3;
Harald Alvestrand719487e2017-12-13 12:26:04 +01001753 expected_audio.packets_lost = -1;
Henrik Boström01738c62019-04-15 17:32:00 +02001754 // |expected_audio.last_packet_received_timestamp| should be undefined.
hboseeafe942016-11-01 03:00:17 -07001755 expected_audio.jitter = 4.5;
1756 expected_audio.fraction_lost = 5.5;
nissec8ee8822017-01-18 07:20:55 -08001757 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001758 EXPECT_EQ(
1759 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1760 expected_audio);
Henrik Boström01738c62019-04-15 17:32:00 +02001761
1762 // Set previously undefined values and "GetStats" again.
1763 voice_media_info.receivers[0].last_packet_received_timestamp_ms = 3000;
1764 expected_audio.last_packet_received_timestamp = 3.0;
1765 voice_media_channel->SetStats(voice_media_info);
1766
1767 report = stats_->GetFreshStatsReport();
1768
1769 ASSERT_TRUE(report->Get(expected_audio.id()));
1770 EXPECT_EQ(
1771 report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
1772 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001773 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001774 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1775 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hboseeafe942016-11-01 03:00:17 -07001776}
1777
1778TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
hboseeafe942016-11-01 03:00:17 -07001779 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001780
hboseeafe942016-11-01 03:00:17 -07001781 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1782 video_media_info.receivers[0].local_stats.push_back(
1783 cricket::SsrcReceiverInfo());
1784 video_media_info.receivers[0].local_stats[0].ssrc = 1;
1785 video_media_info.receivers[0].packets_rcvd = 2;
hbos02cd4d62016-12-09 04:19:44 -08001786 video_media_info.receivers[0].packets_lost = 42;
hboseeafe942016-11-01 03:00:17 -07001787 video_media_info.receivers[0].bytes_rcvd = 3;
1788 video_media_info.receivers[0].fraction_lost = 4.5f;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001789 video_media_info.receivers[0].codec_payload_type = 42;
hbos820f5782016-11-22 03:16:50 -08001790 video_media_info.receivers[0].firs_sent = 5;
1791 video_media_info.receivers[0].plis_sent = 6;
1792 video_media_info.receivers[0].nacks_sent = 7;
hbos6769c492017-01-02 08:35:13 -08001793 video_media_info.receivers[0].frames_decoded = 8;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001794 video_media_info.receivers[0].qp_sum = absl::nullopt;
Henrik Boström01738c62019-04-15 17:32:00 +02001795 video_media_info.receivers[0].last_packet_received_timestamp_ms =
1796 absl::nullopt;
Henrik Boström2e069262019-04-09 13:59:31 +02001797 video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
hbos0adb8282016-11-23 02:32:06 -08001798
1799 RtpCodecParameters codec_parameters;
1800 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001801 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1802 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001803 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001804 video_media_info.receive_codecs.insert(
1805 std::make_pair(codec_parameters.payload_type, codec_parameters));
1806
Steve Anton57858b32018-02-15 15:19:50 -08001807 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001808 video_media_channel->SetStats(video_media_info);
Henrik Boström5b3541f2018-03-19 13:52:56 +01001809 stats_->SetupRemoteTrackAndReceiver(
1810 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", "RemoteStreamId", 1);
hboseeafe942016-11-01 03:00:17 -07001811
Steve Anton5b387312018-02-02 16:00:20 -08001812 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hboseeafe942016-11-01 03:00:17 -07001813
Yves Gerey665174f2018-06-19 15:03:05 +02001814 RTCInboundRTPStreamStats expected_video("RTCInboundRTPVideoStream_1",
1815 report->timestamp_us());
hbos3443bb72017-02-07 06:28:11 -08001816 expected_video.ssrc = 1;
hbos820f5782016-11-22 03:16:50 -08001817 expected_video.is_remote = false;
1818 expected_video.media_type = "video";
Philipp Hancke3bc01662018-08-28 14:55:03 +02001819 expected_video.kind = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001820 expected_video.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001821 expected_video.transport_id = "RTCTransport_TransportName_1";
1822 expected_video.codec_id = "RTCCodec_VideoMid_Inbound_42";
hbos820f5782016-11-22 03:16:50 -08001823 expected_video.fir_count = 5;
1824 expected_video.pli_count = 6;
1825 expected_video.nack_count = 7;
1826 expected_video.packets_received = 2;
1827 expected_video.bytes_received = 3;
hbos02cd4d62016-12-09 04:19:44 -08001828 expected_video.packets_lost = 42;
hbos820f5782016-11-22 03:16:50 -08001829 expected_video.fraction_lost = 4.5;
hbos6769c492017-01-02 08:35:13 -08001830 expected_video.frames_decoded = 8;
hbosa51d4f32017-02-16 05:34:48 -08001831 // |expected_video.qp_sum| should be undefined.
Henrik Boström01738c62019-04-15 17:32:00 +02001832 // |expected_video.last_packet_received_timestamp| should be undefined.
Henrik Boström2e069262019-04-09 13:59:31 +02001833 // |expected_video.content_type| should be undefined.
hboseeafe942016-11-01 03:00:17 -07001834
nissec8ee8822017-01-18 07:20:55 -08001835 ASSERT_TRUE(report->Get(expected_video.id()));
hbosa51d4f32017-02-16 05:34:48 -08001836 EXPECT_EQ(
1837 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1838 expected_video);
hboseeafe942016-11-01 03:00:17 -07001839
hbosa51d4f32017-02-16 05:34:48 -08001840 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001841 video_media_info.receivers[0].qp_sum = 9;
Henrik Boström01738c62019-04-15 17:32:00 +02001842 video_media_info.receivers[0].last_packet_received_timestamp_ms = 1000;
hbosa51d4f32017-02-16 05:34:48 -08001843 expected_video.qp_sum = 9;
Henrik Boström01738c62019-04-15 17:32:00 +02001844 expected_video.last_packet_received_timestamp = 1.0;
Henrik Boström2e069262019-04-09 13:59:31 +02001845 video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
1846 expected_video.content_type = "screenshare";
Steve Anton5b387312018-02-02 16:00:20 -08001847 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001848
Steve Anton5b387312018-02-02 16:00:20 -08001849 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001850
1851 ASSERT_TRUE(report->Get(expected_video.id()));
1852 EXPECT_EQ(
1853 report->Get(expected_video.id())->cast_to<RTCInboundRTPStreamStats>(),
1854 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08001855 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08001856 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbosa51d4f32017-02-16 05:34:48 -08001857 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hboseeafe942016-11-01 03:00:17 -07001858}
1859
hbos6ded1902016-11-01 01:50:46 -07001860TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
hbos6ded1902016-11-01 01:50:46 -07001861 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001862
hbos6ded1902016-11-01 01:50:46 -07001863 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1864 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1865 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1866 voice_media_info.senders[0].packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001867 voice_media_info.senders[0].retransmitted_packets_sent = 20;
hbos6ded1902016-11-01 01:50:46 -07001868 voice_media_info.senders[0].bytes_sent = 3;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001869 voice_media_info.senders[0].retransmitted_bytes_sent = 30;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001870 voice_media_info.senders[0].codec_payload_type = 42;
hbos0adb8282016-11-23 02:32:06 -08001871
1872 RtpCodecParameters codec_parameters;
1873 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001874 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1875 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001876 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001877 voice_media_info.send_codecs.insert(
1878 std::make_pair(codec_parameters.payload_type, codec_parameters));
1879
Steve Anton57858b32018-02-15 15:19:50 -08001880 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001881 voice_media_channel->SetStats(voice_media_info);
1882 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
Henrik Boström646fda02019-05-22 15:49:42 +02001883 "LocalAudioTrackID", 1, true,
1884 /*attachment_id=*/50);
hbos6ded1902016-11-01 01:50:46 -07001885
Steve Anton5b387312018-02-02 16:00:20 -08001886 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001887
Yves Gerey665174f2018-06-19 15:03:05 +02001888 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
1889 report->timestamp_us());
Henrik Boström646fda02019-05-22 15:49:42 +02001890 expected_audio.media_source_id = "RTCAudioSource_50";
hbos3443bb72017-02-07 06:28:11 -08001891 expected_audio.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001892 expected_audio.is_remote = false;
1893 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 14:55:03 +02001894 expected_audio.kind = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001895 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08001896 expected_audio.transport_id = "RTCTransport_TransportName_1";
1897 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001898 expected_audio.packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001899 expected_audio.retransmitted_packets_sent = 20;
hbos6ded1902016-11-01 01:50:46 -07001900 expected_audio.bytes_sent = 3;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001901 expected_audio.retransmitted_bytes_sent = 30;
hboscd195be2017-02-07 08:31:27 -08001902
hboscd195be2017-02-07 08:31:27 -08001903 ASSERT_TRUE(report->Get(expected_audio.id()));
hbosa51d4f32017-02-16 05:34:48 -08001904 EXPECT_EQ(
1905 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1906 expected_audio);
skvladed02c6d2017-02-07 10:45:31 -08001907
hbosa51d4f32017-02-16 05:34:48 -08001908 ASSERT_TRUE(report->Get(expected_audio.id()));
1909 EXPECT_EQ(
1910 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
1911 expected_audio);
hbosb0ae9202017-01-27 06:35:16 -08001912 EXPECT_TRUE(report->Get(*expected_audio.track_id));
hbos84abeb12017-01-16 06:16:44 -08001913 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1914 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001915}
1916
1917TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
hbos6ded1902016-11-01 01:50:46 -07001918 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001919
hbos6ded1902016-11-01 01:50:46 -07001920 video_media_info.senders.push_back(cricket::VideoSenderInfo());
1921 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1922 video_media_info.senders[0].local_stats[0].ssrc = 1;
1923 video_media_info.senders[0].firs_rcvd = 2;
1924 video_media_info.senders[0].plis_rcvd = 3;
1925 video_media_info.senders[0].nacks_rcvd = 4;
1926 video_media_info.senders[0].packets_sent = 5;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001927 video_media_info.senders[0].retransmitted_packets_sent = 50;
hbos6ded1902016-11-01 01:50:46 -07001928 video_media_info.senders[0].bytes_sent = 6;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001929 video_media_info.senders[0].retransmitted_bytes_sent = 60;
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001930 video_media_info.senders[0].codec_payload_type = 42;
hbos6769c492017-01-02 08:35:13 -08001931 video_media_info.senders[0].frames_encoded = 8;
Henrik Boströmf71362f2019-04-08 16:14:23 +02001932 video_media_info.senders[0].total_encode_time_ms = 9000;
Henrik Boström23aff9b2019-05-20 15:15:38 +02001933 video_media_info.senders[0].total_encoded_bytes_target = 1234;
Henrik Boström9fe18342019-05-16 18:38:20 +02001934 video_media_info.senders[0].total_packet_send_delay_ms = 10000;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +02001935 video_media_info.senders[0].qp_sum = absl::nullopt;
Henrik Boström2e069262019-04-09 13:59:31 +02001936 video_media_info.senders[0].content_type = VideoContentType::UNSPECIFIED;
hbos0adb8282016-11-23 02:32:06 -08001937
1938 RtpCodecParameters codec_parameters;
1939 codec_parameters.payload_type = 42;
deadbeefe702b302017-02-04 12:09:01 -08001940 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
1941 codec_parameters.name = "dummy";
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001942 codec_parameters.clock_rate = 0;
hbos0adb8282016-11-23 02:32:06 -08001943 video_media_info.send_codecs.insert(
1944 std::make_pair(codec_parameters.payload_type, codec_parameters));
1945
Steve Anton57858b32018-02-15 15:19:50 -08001946 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08001947 video_media_channel->SetStats(video_media_info);
1948 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_VIDEO,
Henrik Boström646fda02019-05-22 15:49:42 +02001949 "LocalVideoTrackID", 1, true,
1950 /*attachment_id=*/50);
hbos6ded1902016-11-01 01:50:46 -07001951
Steve Anton5b387312018-02-02 16:00:20 -08001952 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos6ded1902016-11-01 01:50:46 -07001953
Harald Alvestranda3dab842018-01-14 09:18:58 +01001954 auto stats_of_my_type = report->GetStatsOfType<RTCOutboundRTPStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001955 ASSERT_EQ(1U, stats_of_my_type.size());
Harald Alvestranda3dab842018-01-14 09:18:58 +01001956 auto stats_of_track_type = report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02001957 ASSERT_EQ(1U, stats_of_track_type.size());
Harald Alvestranda3dab842018-01-14 09:18:58 +01001958
1959 RTCOutboundRTPStreamStats expected_video(stats_of_my_type[0]->id(),
1960 report->timestamp_us());
Henrik Boström646fda02019-05-22 15:49:42 +02001961 expected_video.media_source_id = "RTCVideoSource_50";
hbos3443bb72017-02-07 06:28:11 -08001962 expected_video.ssrc = 1;
hbos6ded1902016-11-01 01:50:46 -07001963 expected_video.is_remote = false;
1964 expected_video.media_type = "video";
Philipp Hancke3bc01662018-08-28 14:55:03 +02001965 expected_video.kind = "video";
Harald Alvestranda3dab842018-01-14 09:18:58 +01001966 expected_video.track_id = stats_of_track_type[0]->id();
Steve Anton57858b32018-02-15 15:19:50 -08001967 expected_video.transport_id = "RTCTransport_TransportName_1";
1968 expected_video.codec_id = "RTCCodec_VideoMid_Outbound_42";
hbos6ded1902016-11-01 01:50:46 -07001969 expected_video.fir_count = 2;
1970 expected_video.pli_count = 3;
1971 expected_video.nack_count = 4;
1972 expected_video.packets_sent = 5;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001973 expected_video.retransmitted_packets_sent = 50;
hbos6ded1902016-11-01 01:50:46 -07001974 expected_video.bytes_sent = 6;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02001975 expected_video.retransmitted_bytes_sent = 60;
skvladed02c6d2017-02-07 10:45:31 -08001976 expected_video.frames_encoded = 8;
Henrik Boströmf71362f2019-04-08 16:14:23 +02001977 expected_video.total_encode_time = 9.0;
Henrik Boström23aff9b2019-05-20 15:15:38 +02001978 expected_video.total_encoded_bytes_target = 1234;
Henrik Boström9fe18342019-05-16 18:38:20 +02001979 expected_video.total_packet_send_delay = 10.0;
Henrik Boström2e069262019-04-09 13:59:31 +02001980 // |expected_video.content_type| should be undefined.
hbosa7a9be12017-03-01 01:02:45 -08001981 // |expected_video.qp_sum| should be undefined.
hboscd195be2017-02-07 08:31:27 -08001982 ASSERT_TRUE(report->Get(expected_video.id()));
Harald Alvestranda3dab842018-01-14 09:18:58 +01001983
hbosa51d4f32017-02-16 05:34:48 -08001984 EXPECT_EQ(
1985 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
1986 expected_video);
skvladed02c6d2017-02-07 10:45:31 -08001987
hbosa51d4f32017-02-16 05:34:48 -08001988 // Set previously undefined values and "GetStats" again.
Oskar Sundbomcbc71b22017-11-16 10:56:07 +01001989 video_media_info.senders[0].qp_sum = 9;
hbosa51d4f32017-02-16 05:34:48 -08001990 expected_video.qp_sum = 9;
Henrik Boström2e069262019-04-09 13:59:31 +02001991 video_media_info.senders[0].content_type = VideoContentType::SCREENSHARE;
1992 expected_video.content_type = "screenshare";
Steve Anton5b387312018-02-02 16:00:20 -08001993 video_media_channel->SetStats(video_media_info);
hbosa51d4f32017-02-16 05:34:48 -08001994
Steve Anton5b387312018-02-02 16:00:20 -08001995 report = stats_->GetFreshStatsReport();
hbosa51d4f32017-02-16 05:34:48 -08001996
1997 ASSERT_TRUE(report->Get(expected_video.id()));
1998 EXPECT_EQ(
1999 report->Get(expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(),
2000 expected_video);
hbosb0ae9202017-01-27 06:35:16 -08002001 EXPECT_TRUE(report->Get(*expected_video.track_id));
hbos84abeb12017-01-16 06:16:44 -08002002 EXPECT_TRUE(report->Get(*expected_video.transport_id));
2003 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hbos6ded1902016-11-01 01:50:46 -07002004}
2005
hbos2fa7c672016-10-24 04:00:05 -07002006TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
Steve Anton5b387312018-02-02 16:00:20 -08002007 const char kTransportName[] = "transport";
2008
2009 pc_->AddVoiceChannel("audio", kTransportName);
2010
Gary Liu37e489c2017-11-21 10:49:36 -08002011 std::unique_ptr<cricket::Candidate> rtp_local_candidate =
2012 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
2013 cricket::LOCAL_PORT_TYPE, 42);
hbos2fa7c672016-10-24 04:00:05 -07002014 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
2015 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08002016 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2017 42);
hbos2fa7c672016-10-24 04:00:05 -07002018 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
Gary Liu37e489c2017-11-21 10:49:36 -08002019 CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI,
hbos2fa7c672016-10-24 04:00:05 -07002020 cricket::LOCAL_PORT_TYPE, 42);
2021 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
2022 CreateFakeCandidate("42.42.42.42", 42, "protocol",
Gary Liu37e489c2017-11-21 10:49:36 -08002023 rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE,
2024 42);
hbos2fa7c672016-10-24 04:00:05 -07002025
hbos2fa7c672016-10-24 04:00:05 -07002026 cricket::ConnectionInfo rtp_connection_info;
2027 rtp_connection_info.best_connection = false;
2028 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
2029 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
2030 rtp_connection_info.sent_total_bytes = 42;
2031 rtp_connection_info.recv_total_bytes = 1337;
2032 cricket::TransportChannelStats rtp_transport_channel_stats;
2033 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
2034 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
hbos7064d592017-01-16 07:38:02 -08002035 rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW;
Steve Anton5b387312018-02-02 16:00:20 -08002036 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07002037
2038 // Get stats without RTCP, an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08002039 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
hbos0583b282016-11-30 01:50:14 -08002040
2041 RTCTransportStats expected_rtp_transport(
2042 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 11:59:48 +02002043 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP),
hbos0583b282016-11-30 01:50:14 -08002044 report->timestamp_us());
2045 expected_rtp_transport.bytes_sent = 42;
2046 expected_rtp_transport.bytes_received = 1337;
hbos7064d592017-01-16 07:38:02 -08002047 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew;
hbos0583b282016-11-30 01:50:14 -08002048
hbosdbb64d82016-12-21 01:57:46 -08002049 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002050 EXPECT_EQ(
2051 expected_rtp_transport,
2052 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07002053
2054 cricket::ConnectionInfo rtcp_connection_info;
2055 rtcp_connection_info.best_connection = false;
2056 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
2057 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
2058 rtcp_connection_info.sent_total_bytes = 1337;
2059 rtcp_connection_info.recv_total_bytes = 42;
2060 cricket::TransportChannelStats rtcp_transport_channel_stats;
2061 rtcp_transport_channel_stats.component =
2062 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
2063 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
hbos7064d592017-01-16 07:38:02 -08002064 rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTING;
Steve Anton5b387312018-02-02 16:00:20 -08002065 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2066 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07002067
hbos2fa7c672016-10-24 04:00:05 -07002068 // Get stats with RTCP and without an active connection or certificates.
Steve Anton5b387312018-02-02 16:00:20 -08002069 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08002070
2071 RTCTransportStats expected_rtcp_transport(
2072 "RTCTransport_transport_" +
Jonas Olsson6b1985d2018-07-05 11:59:48 +02002073 rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTCP),
hbos0583b282016-11-30 01:50:14 -08002074 report->timestamp_us());
2075 expected_rtcp_transport.bytes_sent = 1337;
2076 expected_rtcp_transport.bytes_received = 42;
hbos7064d592017-01-16 07:38:02 -08002077 expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting;
hbos0583b282016-11-30 01:50:14 -08002078
2079 expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id();
2080
hbosdbb64d82016-12-21 01:57:46 -08002081 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002082 EXPECT_EQ(
2083 expected_rtp_transport,
2084 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08002085 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002086 EXPECT_EQ(
2087 expected_rtcp_transport,
2088 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07002089
hbos7064d592017-01-16 07:38:02 -08002090 // Get stats with an active connection (selected candidate pair).
Steve Anton5b387312018-02-02 16:00:20 -08002091 rtcp_transport_channel_stats.connection_infos[0].best_connection = true;
2092 pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats,
2093 rtcp_transport_channel_stats});
hbos2fa7c672016-10-24 04:00:05 -07002094
Steve Anton5b387312018-02-02 16:00:20 -08002095 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08002096
hbos0583b282016-11-30 01:50:14 -08002097 expected_rtcp_transport.selected_candidate_pair_id =
2098 "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" +
2099 rtcp_remote_candidate->id();
2100
hbosdbb64d82016-12-21 01:57:46 -08002101 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002102 EXPECT_EQ(
2103 expected_rtp_transport,
2104 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08002105 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002106 EXPECT_EQ(
2107 expected_rtcp_transport,
2108 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07002109
2110 // Get stats with certificates.
2111 std::unique_ptr<CertificateInfo> local_certinfo =
Steve Anton5b387312018-02-02 16:00:20 -08002112 CreateFakeCertificateAndInfoFromDers({"(local) local", "(local) chain"});
2113 pc_->SetLocalCertificate(kTransportName, local_certinfo->certificate);
hbos2fa7c672016-10-24 04:00:05 -07002114 std::unique_ptr<CertificateInfo> remote_certinfo =
2115 CreateFakeCertificateAndInfoFromDers(
Steve Anton5b387312018-02-02 16:00:20 -08002116 {"(remote) local", "(remote) chain"});
Taylor Brandstetterc3928662018-02-23 13:04:51 -08002117 pc_->SetRemoteCertChain(
Benjamin Wright6c6c9df2018-10-25 01:16:26 -07002118 kTransportName,
2119 remote_certinfo->certificate->GetSSLCertificateChain().Clone());
hbos2fa7c672016-10-24 04:00:05 -07002120
Steve Anton5b387312018-02-02 16:00:20 -08002121 report = stats_->GetFreshStatsReport();
hbos0583b282016-11-30 01:50:14 -08002122
2123 expected_rtp_transport.local_certificate_id =
2124 "RTCCertificate_" + local_certinfo->fingerprints[0];
2125 expected_rtp_transport.remote_certificate_id =
2126 "RTCCertificate_" + remote_certinfo->fingerprints[0];
2127
2128 expected_rtcp_transport.local_certificate_id =
2129 *expected_rtp_transport.local_certificate_id;
2130 expected_rtcp_transport.remote_certificate_id =
2131 *expected_rtp_transport.remote_certificate_id;
2132
hbosdbb64d82016-12-21 01:57:46 -08002133 ASSERT_TRUE(report->Get(expected_rtp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002134 EXPECT_EQ(
2135 expected_rtp_transport,
2136 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>());
hbosdbb64d82016-12-21 01:57:46 -08002137 ASSERT_TRUE(report->Get(expected_rtcp_transport.id()));
hbos0583b282016-11-30 01:50:14 -08002138 EXPECT_EQ(
2139 expected_rtcp_transport,
2140 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>());
hbos2fa7c672016-10-24 04:00:05 -07002141}
2142
Harald Alvestrand89061872018-01-02 14:08:34 +01002143TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) {
Harald Alvestrand89061872018-01-02 14:08:34 +01002144 cricket::VoiceMediaInfo voice_media_info;
2145
2146 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2147 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2148 voice_media_info.senders[0].local_stats[0].ssrc = 1;
2149 voice_media_info.senders[0].packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02002150 voice_media_info.senders[0].retransmitted_packets_sent = 20;
Harald Alvestrand89061872018-01-02 14:08:34 +01002151 voice_media_info.senders[0].bytes_sent = 3;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02002152 voice_media_info.senders[0].retransmitted_bytes_sent = 30;
Harald Alvestrand89061872018-01-02 14:08:34 +01002153 voice_media_info.senders[0].codec_payload_type = 42;
2154
2155 RtpCodecParameters codec_parameters;
2156 codec_parameters.payload_type = 42;
2157 codec_parameters.kind = cricket::MEDIA_TYPE_AUDIO;
2158 codec_parameters.name = "dummy";
2159 codec_parameters.clock_rate = 0;
2160 voice_media_info.send_codecs.insert(
2161 std::make_pair(codec_parameters.payload_type, codec_parameters));
2162
Steve Anton5b387312018-02-02 16:00:20 -08002163 // Emulates the case where AddTrack is used without an associated MediaStream
Steve Anton57858b32018-02-15 15:19:50 -08002164 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
Steve Anton5b387312018-02-02 16:00:20 -08002165 voice_media_channel->SetStats(voice_media_info);
2166 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
Henrik Boström646fda02019-05-22 15:49:42 +02002167 "LocalAudioTrackID", 1, false,
2168 /*attachment_id=*/50);
Harald Alvestrand89061872018-01-02 14:08:34 +01002169
Steve Anton5b387312018-02-02 16:00:20 -08002170 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
Harald Alvestrand89061872018-01-02 14:08:34 +01002171
2172 RTCOutboundRTPStreamStats expected_audio("RTCOutboundRTPAudioStream_1",
2173 report->timestamp_us());
Henrik Boström646fda02019-05-22 15:49:42 +02002174 expected_audio.media_source_id = "RTCAudioSource_50";
Harald Alvestrand89061872018-01-02 14:08:34 +01002175 expected_audio.ssrc = 1;
2176 expected_audio.is_remote = false;
2177 expected_audio.media_type = "audio";
Philipp Hancke3bc01662018-08-28 14:55:03 +02002178 expected_audio.kind = "audio";
Harald Alvestranda3dab842018-01-14 09:18:58 +01002179 expected_audio.track_id = IdForType<RTCMediaStreamTrackStats>(report);
Steve Anton57858b32018-02-15 15:19:50 -08002180 expected_audio.transport_id = "RTCTransport_TransportName_1";
2181 expected_audio.codec_id = "RTCCodec_AudioMid_Outbound_42";
Harald Alvestrand89061872018-01-02 14:08:34 +01002182 expected_audio.packets_sent = 2;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02002183 expected_audio.retransmitted_packets_sent = 20;
Harald Alvestrand89061872018-01-02 14:08:34 +01002184 expected_audio.bytes_sent = 3;
Henrik Boströmcf96e0f2019-04-17 13:51:53 +02002185 expected_audio.retransmitted_bytes_sent = 30;
Harald Alvestrand89061872018-01-02 14:08:34 +01002186
2187 ASSERT_TRUE(report->Get(expected_audio.id()));
2188 EXPECT_EQ(
2189 report->Get(expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(),
2190 expected_audio);
Harald Alvestrand89061872018-01-02 14:08:34 +01002191 EXPECT_TRUE(report->Get(*expected_audio.track_id));
2192 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
2193 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
2194}
2195
Henrik Boström646fda02019-05-22 15:49:42 +02002196TEST_F(RTCStatsCollectorTest, RTCAudioSourceStatsCollectedForSenderWithTrack) {
2197 const uint32_t kSsrc = 4;
2198 const int kAttachmentId = 42;
2199
2200 cricket::VoiceMediaInfo voice_media_info;
2201 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2202 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2203 voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2204 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
2205 voice_media_channel->SetStats(voice_media_info);
2206 stats_->SetupLocalTrackAndSender(cricket::MEDIA_TYPE_AUDIO,
2207 "LocalAudioTrackID", kSsrc, false,
2208 kAttachmentId);
2209
2210 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2211
2212 RTCAudioSourceStats expected_audio("RTCAudioSource_42",
2213 report->timestamp_us());
2214 expected_audio.track_identifier = "LocalAudioTrackID";
2215 expected_audio.kind = "audio";
2216
2217 ASSERT_TRUE(report->Get(expected_audio.id()));
2218 EXPECT_EQ(report->Get(expected_audio.id())->cast_to<RTCAudioSourceStats>(),
2219 expected_audio);
2220}
2221
2222TEST_F(RTCStatsCollectorTest, RTCVideoSourceStatsCollectedForSenderWithTrack) {
2223 const uint32_t kSsrc = 4;
2224 const int kAttachmentId = 42;
2225 const int kVideoSourceWidth = 12;
2226 const int kVideoSourceHeight = 34;
2227
2228 cricket::VideoMediaInfo video_media_info;
2229 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2230 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2231 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2232 video_media_info.senders[0].framerate_input = 29;
2233 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2234 video_media_channel->SetStats(video_media_info);
2235
2236 auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2237 kVideoSourceHeight);
2238 auto video_track = FakeVideoTrackForStats::Create(
2239 "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2240 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2241 cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
2242 pc_->AddSender(sender);
2243
2244 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2245
2246 RTCVideoSourceStats expected_video("RTCVideoSource_42",
2247 report->timestamp_us());
2248 expected_video.track_identifier = "LocalVideoTrackID";
2249 expected_video.kind = "video";
2250 expected_video.width = kVideoSourceWidth;
2251 expected_video.height = kVideoSourceHeight;
2252 // |expected_video.frames| is expected to be undefined because it is not set.
2253 // TODO(hbos): When implemented, set its expected value here.
2254 expected_video.frames_per_second = 29;
2255
2256 ASSERT_TRUE(report->Get(expected_video.id()));
2257 EXPECT_EQ(report->Get(expected_video.id())->cast_to<RTCVideoSourceStats>(),
2258 expected_video);
2259}
2260
2261// This test exercises the current behavior and code path, but the correct
2262// behavior is to report frame rate even if we have no SSRC.
2263// TODO(hbos): When we know the frame rate even if we have no SSRC, update the
2264// expectations of this test.
2265TEST_F(RTCStatsCollectorTest,
2266 RTCVideoSourceStatsMissingFrameRateWhenSenderHasNoSsrc) {
2267 // TODO(https://crbug.com/webrtc/8694): When 0 is no longer a magic value for
2268 // "none", update this test.
2269 const uint32_t kNoSsrc = 0;
2270 const int kAttachmentId = 42;
2271 const int kVideoSourceWidth = 12;
2272 const int kVideoSourceHeight = 34;
2273
2274 cricket::VideoMediaInfo video_media_info;
2275 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2276 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2277 video_media_info.senders[0].framerate_input = 29;
2278 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2279 video_media_channel->SetStats(video_media_info);
2280
2281 auto video_source = FakeVideoTrackSourceForStats::Create(kVideoSourceWidth,
2282 kVideoSourceHeight);
2283 auto video_track = FakeVideoTrackForStats::Create(
2284 "LocalVideoTrackID", MediaStreamTrackInterface::kLive, video_source);
2285 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2286 cricket::MEDIA_TYPE_VIDEO, video_track, kNoSsrc, kAttachmentId, {});
2287 pc_->AddSender(sender);
2288
2289 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2290 ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2291 auto video_stats =
2292 report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2293 EXPECT_FALSE(video_stats.frames_per_second.is_defined());
2294}
2295
2296// The track not having a source is not expected to be true in practise, but
2297// this is true in some tests relying on fakes. This test covers that code path.
2298TEST_F(RTCStatsCollectorTest,
2299 RTCVideoSourceStatsMissingResolutionWhenTrackHasNoSource) {
2300 const uint32_t kSsrc = 4;
2301 const int kAttachmentId = 42;
2302
2303 cricket::VideoMediaInfo video_media_info;
2304 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2305 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2306 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2307 video_media_info.senders[0].framerate_input = 29;
2308 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2309 video_media_channel->SetStats(video_media_info);
2310
2311 auto video_track = FakeVideoTrackForStats::Create(
2312 "LocalVideoTrackID", MediaStreamTrackInterface::kLive,
2313 /*source=*/nullptr);
2314 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2315 cricket::MEDIA_TYPE_VIDEO, video_track, kSsrc, kAttachmentId, {});
2316 pc_->AddSender(sender);
2317
2318 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2319 ASSERT_TRUE(report->Get("RTCVideoSource_42"));
2320 auto video_stats =
2321 report->Get("RTCVideoSource_42")->cast_to<RTCVideoSourceStats>();
2322 EXPECT_FALSE(video_stats.width.is_defined());
2323 EXPECT_FALSE(video_stats.height.is_defined());
2324}
2325
2326TEST_F(RTCStatsCollectorTest,
2327 RTCAudioSourceStatsNotCollectedForSenderWithoutTrack) {
2328 const uint32_t kSsrc = 4;
2329 const int kAttachmentId = 42;
2330
2331 cricket::VoiceMediaInfo voice_media_info;
2332 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
2333 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2334 voice_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2335 auto* voice_media_channel = pc_->AddVoiceChannel("AudioMid", "TransportName");
2336 voice_media_channel->SetStats(voice_media_info);
2337 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2338 cricket::MEDIA_TYPE_AUDIO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
2339 pc_->AddSender(sender);
2340
2341 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2342 EXPECT_FALSE(report->Get("RTCAudioSource_42"));
2343}
2344
2345TEST_F(RTCStatsCollectorTest,
2346 RTCVideoSourceStatsNotCollectedForSenderWithoutTrack) {
2347 const uint32_t kSsrc = 4;
2348 const int kAttachmentId = 42;
2349
2350 cricket::VideoMediaInfo video_media_info;
2351 video_media_info.senders.push_back(cricket::VideoSenderInfo());
2352 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
2353 video_media_info.senders[0].local_stats[0].ssrc = kSsrc;
2354 video_media_info.senders[0].framerate_input = 29;
2355 auto* video_media_channel = pc_->AddVideoChannel("VideoMid", "TransportName");
2356 video_media_channel->SetStats(video_media_info);
2357
2358 rtc::scoped_refptr<MockRtpSenderInternal> sender = CreateMockSender(
2359 cricket::MEDIA_TYPE_VIDEO, /*track=*/nullptr, kSsrc, kAttachmentId, {});
2360 pc_->AddSender(sender);
2361
2362 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2363 EXPECT_FALSE(report->Get("RTCVideoSource_42"));
2364}
2365
Henrik Boström5b3541f2018-03-19 13:52:56 +01002366TEST_F(RTCStatsCollectorTest, GetStatsWithSenderSelector) {
2367 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2368 // Expected stats graph when filtered by sender:
2369 //
Henrik Boström646fda02019-05-22 15:49:42 +02002370 // +--- track (sender)
2371 // | ^
2372 // | |
2373 // | +--------- outbound-rtp
2374 // | | | |
2375 // | | v v
2376 // | | codec (send) transport
2377 // v v
2378 // media-source
Henrik Boström5b3541f2018-03-19 13:52:56 +01002379 rtc::scoped_refptr<const RTCStatsReport> sender_report =
2380 stats_->GetStatsReportWithSenderSelector(graph.sender);
2381 EXPECT_TRUE(sender_report);
2382 EXPECT_EQ(sender_report->timestamp_us(), graph.full_report->timestamp_us());
Henrik Boström646fda02019-05-22 15:49:42 +02002383 EXPECT_EQ(sender_report->size(), 5u);
Henrik Boström5b3541f2018-03-19 13:52:56 +01002384 EXPECT_TRUE(sender_report->Get(graph.send_codec_id));
2385 EXPECT_FALSE(sender_report->Get(graph.recv_codec_id));
2386 EXPECT_TRUE(sender_report->Get(graph.outbound_rtp_id));
2387 EXPECT_FALSE(sender_report->Get(graph.inbound_rtp_id));
2388 EXPECT_TRUE(sender_report->Get(graph.transport_id));
2389 EXPECT_TRUE(sender_report->Get(graph.sender_track_id));
2390 EXPECT_FALSE(sender_report->Get(graph.receiver_track_id));
2391 EXPECT_FALSE(sender_report->Get(graph.remote_stream_id));
2392 EXPECT_FALSE(sender_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 15:49:42 +02002393 EXPECT_TRUE(sender_report->Get(graph.media_source_id));
Henrik Boström5b3541f2018-03-19 13:52:56 +01002394}
2395
2396TEST_F(RTCStatsCollectorTest, GetStatsWithReceiverSelector) {
2397 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2398 // Expected stats graph when filtered by receiver:
2399 //
Henrik Boström646fda02019-05-22 15:49:42 +02002400 // track (receiver)
2401 // ^
2402 // |
2403 // inbound-rtp ---------------+
2404 // | |
2405 // v v
2406 // transport codec (recv)
Henrik Boström5b3541f2018-03-19 13:52:56 +01002407 rtc::scoped_refptr<const RTCStatsReport> receiver_report =
2408 stats_->GetStatsReportWithReceiverSelector(graph.receiver);
2409 EXPECT_TRUE(receiver_report);
2410 EXPECT_EQ(receiver_report->size(), 4u);
2411 EXPECT_EQ(receiver_report->timestamp_us(), graph.full_report->timestamp_us());
2412 EXPECT_FALSE(receiver_report->Get(graph.send_codec_id));
2413 EXPECT_TRUE(receiver_report->Get(graph.recv_codec_id));
2414 EXPECT_FALSE(receiver_report->Get(graph.outbound_rtp_id));
2415 EXPECT_TRUE(receiver_report->Get(graph.inbound_rtp_id));
2416 EXPECT_TRUE(receiver_report->Get(graph.transport_id));
2417 EXPECT_FALSE(receiver_report->Get(graph.sender_track_id));
2418 EXPECT_TRUE(receiver_report->Get(graph.receiver_track_id));
2419 EXPECT_FALSE(receiver_report->Get(graph.remote_stream_id));
2420 EXPECT_FALSE(receiver_report->Get(graph.peer_connection_id));
Henrik Boström646fda02019-05-22 15:49:42 +02002421 EXPECT_FALSE(receiver_report->Get(graph.media_source_id));
Henrik Boström5b3541f2018-03-19 13:52:56 +01002422}
2423
2424TEST_F(RTCStatsCollectorTest, GetStatsWithNullSenderSelector) {
2425 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2426 rtc::scoped_refptr<const RTCStatsReport> empty_report =
2427 stats_->GetStatsReportWithSenderSelector(nullptr);
2428 EXPECT_TRUE(empty_report);
2429 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2430 EXPECT_EQ(empty_report->size(), 0u);
2431}
2432
2433TEST_F(RTCStatsCollectorTest, GetStatsWithNullReceiverSelector) {
2434 ExampleStatsGraph graph = SetupExampleStatsGraphForSelectorTests();
2435 rtc::scoped_refptr<const RTCStatsReport> empty_report =
2436 stats_->GetStatsReportWithReceiverSelector(nullptr);
2437 EXPECT_TRUE(empty_report);
2438 EXPECT_EQ(empty_report->timestamp_us(), graph.full_report->timestamp_us());
2439 EXPECT_EQ(empty_report->size(), 0u);
2440}
2441
Harald Alvestrand89061872018-01-02 14:08:34 +01002442// When the PC has not had SetLocalDescription done, tracks all have
2443// SSRC 0, meaning "unconnected".
Harald Alvestrandb8e12012018-01-23 15:28:16 +01002444// In this state, we report on track stats, but not RTP stats.
2445TEST_F(RTCStatsCollectorTest, StatsReportedOnZeroSsrc) {
Harald Alvestrand89061872018-01-02 14:08:34 +01002446 rtc::scoped_refptr<MediaStreamTrackInterface> track =
2447 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2448 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08002449 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 15:49:42 +02002450 CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 0, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08002451 pc_->AddSender(sender);
2452
2453 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2454
Harald Alvestrand89061872018-01-02 14:08:34 +01002455 std::vector<const RTCMediaStreamTrackStats*> track_stats =
2456 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02002457 EXPECT_EQ(1U, track_stats.size());
Steve Anton5b387312018-02-02 16:00:20 -08002458
Harald Alvestrandb8e12012018-01-23 15:28:16 +01002459 std::vector<const RTCRTPStreamStats*> rtp_stream_stats =
2460 report->GetStatsOfType<RTCRTPStreamStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02002461 EXPECT_EQ(0U, rtp_stream_stats.size());
Harald Alvestrand89061872018-01-02 14:08:34 +01002462}
2463
Harald Alvestrand76d29522018-01-30 14:43:29 +01002464TEST_F(RTCStatsCollectorTest, DoNotCrashOnSsrcChange) {
2465 rtc::scoped_refptr<MediaStreamTrackInterface> track =
2466 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
2467 MediaStreamTrackInterface::kLive);
Steve Anton57858b32018-02-15 15:19:50 -08002468 rtc::scoped_refptr<MockRtpSenderInternal> sender =
Henrik Boström646fda02019-05-22 15:49:42 +02002469 CreateMockSender(cricket::MEDIA_TYPE_AUDIO, track, 4711, 49, {});
Steve Anton5b387312018-02-02 16:00:20 -08002470 pc_->AddSender(sender);
2471
Harald Alvestrand76d29522018-01-30 14:43:29 +01002472 // We do not generate any matching voice_sender_info stats.
Steve Anton5b387312018-02-02 16:00:20 -08002473 rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport();
2474
Harald Alvestrand76d29522018-01-30 14:43:29 +01002475 std::vector<const RTCMediaStreamTrackStats*> track_stats =
2476 report->GetStatsOfType<RTCMediaStreamTrackStats>();
Mirko Bonadeie12c1fe2018-07-03 12:53:23 +02002477 EXPECT_EQ(1U, track_stats.size());
Harald Alvestrand76d29522018-01-30 14:43:29 +01002478}
2479
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002480// Used for test below, to test calling GetStatsReport during a callback.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002481class RecursiveCallback : public RTCStatsCollectorCallback {
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002482 public:
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002483 explicit RecursiveCallback(RTCStatsCollectorWrapper* stats) : stats_(stats) {}
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002484
2485 void OnStatsDelivered(
2486 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
2487 stats_->GetStatsReport();
2488 called_ = true;
2489 }
2490
2491 bool called() const { return called_; }
2492
2493 private:
2494 RTCStatsCollectorWrapper* stats_;
2495 bool called_ = false;
2496};
2497
2498// Test that nothing bad happens if a callback causes GetStatsReport to be
2499// called again recursively. Regression test for crbug.com/webrtc/8973.
Taylor Brandstetter25e022f2018-03-08 09:53:47 -08002500TEST_F(RTCStatsCollectorTest, DoNotCrashWhenGetStatsCalledDuringCallback) {
2501 rtc::scoped_refptr<RecursiveCallback> callback1(
2502 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
2503 rtc::scoped_refptr<RecursiveCallback> callback2(
2504 new rtc::RefCountedObject<RecursiveCallback>(stats_.get()));
Taylor Brandstetter87d5a742018-03-06 09:42:25 -08002505 stats_->stats_collector()->GetStatsReport(callback1);
2506 stats_->stats_collector()->GetStatsReport(callback2);
2507 EXPECT_TRUE_WAIT(callback1->called(), kGetStatsReportTimeoutMs);
2508 EXPECT_TRUE_WAIT(callback2->called(), kGetStatsReportTimeoutMs);
2509}
2510
Steve Anton5b387312018-02-02 16:00:20 -08002511class RTCTestStats : public RTCStats {
hbosc82f2e12016-09-05 01:36:50 -07002512 public:
Steve Anton5b387312018-02-02 16:00:20 -08002513 WEBRTC_RTCSTATS_DECL();
2514
2515 RTCTestStats(const std::string& id, int64_t timestamp_us)
2516 : RTCStats(id, timestamp_us), dummy_stat("dummyStat") {}
2517
2518 RTCStatsMember<int32_t> dummy_stat;
2519};
2520
Mirko Bonadeic4dd7302019-02-25 09:12:02 +01002521WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", &dummy_stat)
Steve Anton5b387312018-02-02 16:00:20 -08002522
2523// Overrides the stats collection to verify thread usage and that the resulting
2524// partial reports are merged.
2525class FakeRTCStatsCollector : public RTCStatsCollector,
2526 public RTCStatsCollectorCallback {
2527 public:
2528 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
2529 PeerConnectionInternal* pc,
2530 int64_t cache_lifetime_us) {
2531 return rtc::scoped_refptr<FakeRTCStatsCollector>(
2532 new rtc::RefCountedObject<FakeRTCStatsCollector>(pc,
2533 cache_lifetime_us));
2534 }
2535
2536 // RTCStatsCollectorCallback implementation.
2537 void OnStatsDelivered(
2538 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
2539 EXPECT_TRUE(signaling_thread_->IsCurrent());
2540 rtc::CritScope cs(&lock_);
2541 delivered_report_ = report;
2542 }
2543
2544 void VerifyThreadUsageAndResultsMerging() {
2545 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
2546 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
2547 }
2548
2549 bool HasVerifiedResults() {
2550 EXPECT_TRUE(signaling_thread_->IsCurrent());
2551 rtc::CritScope cs(&lock_);
2552 if (!delivered_report_)
2553 return false;
2554 EXPECT_EQ(produced_on_signaling_thread_, 1);
2555 EXPECT_EQ(produced_on_network_thread_, 1);
2556
2557 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
2558 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
2559
2560 produced_on_signaling_thread_ = 0;
2561 produced_on_network_thread_ = 0;
2562 delivered_report_ = nullptr;
2563 return true;
hbosc82f2e12016-09-05 01:36:50 -07002564 }
2565
2566 protected:
Steve Anton5b387312018-02-02 16:00:20 -08002567 FakeRTCStatsCollector(PeerConnectionInternal* pc, int64_t cache_lifetime)
2568 : RTCStatsCollector(pc, cache_lifetime),
2569 signaling_thread_(pc->signaling_thread()),
2570 worker_thread_(pc->worker_thread()),
2571 network_thread_(pc->network_thread()) {}
2572
Henrik Boström40b030e2019-02-28 09:49:31 +01002573 void ProducePartialResultsOnSignalingThreadImpl(
2574 int64_t timestamp_us,
2575 RTCStatsReport* partial_report) override {
Steve Anton5b387312018-02-02 16:00:20 -08002576 EXPECT_TRUE(signaling_thread_->IsCurrent());
2577 {
2578 rtc::CritScope cs(&lock_);
2579 EXPECT_FALSE(delivered_report_);
2580 ++produced_on_signaling_thread_;
2581 }
2582
Henrik Boström40b030e2019-02-28 09:49:31 +01002583 partial_report->AddStats(std::unique_ptr<const RTCStats>(
Steve Anton5b387312018-02-02 16:00:20 -08002584 new RTCTestStats("SignalingThreadStats", timestamp_us)));
Steve Anton5b387312018-02-02 16:00:20 -08002585 }
Henrik Boström40b030e2019-02-28 09:49:31 +01002586 void ProducePartialResultsOnNetworkThreadImpl(
2587 int64_t timestamp_us,
2588 const std::map<std::string, cricket::TransportStats>&
2589 transport_stats_by_name,
2590 const std::map<std::string, CertificateStatsPair>& transport_cert_stats,
2591 RTCStatsReport* partial_report) override {
Steve Anton5b387312018-02-02 16:00:20 -08002592 EXPECT_TRUE(network_thread_->IsCurrent());
2593 {
2594 rtc::CritScope cs(&lock_);
2595 EXPECT_FALSE(delivered_report_);
2596 ++produced_on_network_thread_;
2597 }
2598
Henrik Boström40b030e2019-02-28 09:49:31 +01002599 partial_report->AddStats(std::unique_ptr<const RTCStats>(
Steve Anton5b387312018-02-02 16:00:20 -08002600 new RTCTestStats("NetworkThreadStats", timestamp_us)));
Steve Anton5b387312018-02-02 16:00:20 -08002601 }
2602
2603 private:
2604 rtc::Thread* const signaling_thread_;
2605 rtc::Thread* const worker_thread_;
2606 rtc::Thread* const network_thread_;
2607
2608 rtc::CriticalSection lock_;
2609 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
2610 int produced_on_signaling_thread_ = 0;
2611 int produced_on_network_thread_ = 0;
hbosc82f2e12016-09-05 01:36:50 -07002612};
2613
Steve Anton5b387312018-02-02 16:00:20 -08002614TEST(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
2615 rtc::scoped_refptr<FakePeerConnectionForStats> pc(
2616 new rtc::RefCountedObject<FakePeerConnectionForStats>());
2617 rtc::scoped_refptr<FakeRTCStatsCollector> stats_collector(
2618 FakeRTCStatsCollector::Create(pc, 50 * rtc::kNumMicrosecsPerMillisec));
2619 stats_collector->VerifyThreadUsageAndResultsMerging();
hbosc82f2e12016-09-05 01:36:50 -07002620}
2621
2622} // namespace
2623
hbosd565b732016-08-30 14:04:35 -07002624} // namespace webrtc