blob: f27eb329800e26254cda4c02ec968382a5c8eaa0 [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
hbos74e1a4f2016-09-15 23:33:01 -070011#include "webrtc/api/rtcstatscollector.h"
hbosd565b732016-08-30 14:04:35 -070012
13#include <memory>
hbosda389e32016-10-25 10:55:08 -070014#include <ostream>
hbosd565b732016-08-30 14:04:35 -070015#include <string>
16#include <vector>
17
hbos0adb8282016-11-23 02:32:06 -080018#include "webrtc/api/jsepsessiondescription.h"
hbos09bc1282016-11-08 06:29:22 -080019#include "webrtc/api/mediastream.h"
20#include "webrtc/api/mediastreamtrack.h"
hbos0adb8282016-11-23 02:32:06 -080021#include "webrtc/api/rtpparameters.h"
hbos74e1a4f2016-09-15 23:33:01 -070022#include "webrtc/api/stats/rtcstats_objects.h"
23#include "webrtc/api/stats/rtcstatsreport.h"
hbosd565b732016-08-30 14:04:35 -070024#include "webrtc/api/test/mock_datachannel.h"
25#include "webrtc/api/test/mock_peerconnection.h"
26#include "webrtc/api/test/mock_webrtcsession.h"
27#include "webrtc/base/checks.h"
hbos0e6758d2016-08-31 07:57:36 -070028#include "webrtc/base/fakeclock.h"
hbos6ab97ce2016-10-03 14:16:56 -070029#include "webrtc/base/fakesslidentity.h"
hbosd565b732016-08-30 14:04:35 -070030#include "webrtc/base/gunit.h"
31#include "webrtc/base/logging.h"
hbosab9f6e42016-10-07 02:18:47 -070032#include "webrtc/base/socketaddress.h"
hbosc82f2e12016-09-05 01:36:50 -070033#include "webrtc/base/thread_checker.h"
hbos0e6758d2016-08-31 07:57:36 -070034#include "webrtc/base/timedelta.h"
35#include "webrtc/base/timeutils.h"
skvlad11a9cbf2016-10-07 11:53:05 -070036#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
hbosd565b732016-08-30 14:04:35 -070037#include "webrtc/media/base/fakemediaengine.h"
hbos6ded1902016-11-01 01:50:46 -070038#include "webrtc/media/base/test/mock_mediachannel.h"
hbos2fa7c672016-10-24 04:00:05 -070039#include "webrtc/p2p/base/p2pconstants.h"
hbosab9f6e42016-10-07 02:18:47 -070040#include "webrtc/p2p/base/port.h"
hbosd565b732016-08-30 14:04:35 -070041
hbos6ab97ce2016-10-03 14:16:56 -070042using testing::_;
43using testing::Invoke;
hbosd565b732016-08-30 14:04:35 -070044using testing::Return;
hbos6ded1902016-11-01 01:50:46 -070045using testing::ReturnNull;
hbosd565b732016-08-30 14:04:35 -070046using testing::ReturnRef;
hbos6ded1902016-11-01 01:50:46 -070047using testing::SetArgPointee;
hbosd565b732016-08-30 14:04:35 -070048
49namespace webrtc {
50
hbosda389e32016-10-25 10:55:08 -070051// These are used by gtest code, such as if |EXPECT_EQ| fails.
52void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
53 *os << stats.ToString();
54}
55
hbos0adb8282016-11-23 02:32:06 -080056void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) {
57 *os << stats.ToString();
58}
59
hbosda389e32016-10-25 10:55:08 -070060void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
61 *os << stats.ToString();
62}
63
64void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
65 *os << stats.ToString();
66}
67
68void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
69 *os << stats.ToString();
70}
71
72void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
73 *os << stats.ToString();
74}
75
76void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
77 *os << stats.ToString();
78}
79
hbos09bc1282016-11-08 06:29:22 -080080void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
81 *os << stats.ToString();
82}
83
84void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
85 *os << stats.ToString();
86}
87
hboseeafe942016-11-01 03:00:17 -070088void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
89 *os << stats.ToString();
90}
91
hbos6ded1902016-11-01 01:50:46 -070092void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
93 *os << stats.ToString();
94}
95
hbosda389e32016-10-25 10:55:08 -070096void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
97 *os << stats.ToString();
98}
99
hbosc82f2e12016-09-05 01:36:50 -0700100namespace {
101
102const int64_t kGetStatsReportTimeoutMs = 1000;
103
hbos6ab97ce2016-10-03 14:16:56 -0700104struct CertificateInfo {
105 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
106 std::vector<std::string> ders;
107 std::vector<std::string> pems;
108 std::vector<std::string> fingerprints;
109};
110
111std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
112 const std::vector<std::string>& ders) {
113 RTC_CHECK(!ders.empty());
114 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
115 info->ders = ders;
116 for (const std::string& der : ders) {
117 info->pems.push_back(rtc::SSLIdentity::DerToPem(
118 "CERTIFICATE",
119 reinterpret_cast<const unsigned char*>(der.c_str()),
120 der.length()));
121 }
122 info->certificate =
123 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
124 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
125 // Strip header/footer and newline characters of PEM strings.
126 for (size_t i = 0; i < info->pems.size(); ++i) {
127 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
128 "", 0, &info->pems[i]);
129 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
130 "", 0, &info->pems[i]);
131 rtc::replace_substrs("\n", 1,
132 "", 0, &info->pems[i]);
133 }
134 // Fingerprint of leaf certificate.
135 std::unique_ptr<rtc::SSLFingerprint> fp(
136 rtc::SSLFingerprint::Create("sha-1",
137 &info->certificate->ssl_certificate()));
138 EXPECT_TRUE(fp);
139 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
140 // Fingerprints of the rest of the chain.
141 std::unique_ptr<rtc::SSLCertChain> chain =
142 info->certificate->ssl_certificate().GetChain();
143 if (chain) {
144 for (size_t i = 0; i < chain->GetSize(); i++) {
145 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
146 EXPECT_TRUE(fp);
147 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
148 }
149 }
150 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
151 return info;
152}
153
hbosab9f6e42016-10-07 02:18:47 -0700154std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
155 const std::string& hostname,
156 int port,
157 const std::string& protocol,
158 const std::string& candidate_type,
159 uint32_t priority) {
160 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
161 candidate->set_address(rtc::SocketAddress(hostname, port));
162 candidate->set_protocol(protocol);
163 candidate->set_type(candidate_type);
164 candidate->set_priority(priority);
165 return candidate;
166}
167
hbos09bc1282016-11-08 06:29:22 -0800168class FakeAudioProcessorForStats
169 : public rtc::RefCountedObject<AudioProcessorInterface> {
170 public:
171 FakeAudioProcessorForStats(
172 AudioProcessorInterface::AudioProcessorStats stats)
173 : stats_(stats) {
174 }
175
176 void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override {
177 *stats = stats_;
178 }
179
180 private:
181 AudioProcessorInterface::AudioProcessorStats stats_;
182};
183
184class FakeAudioTrackForStats
185 : public MediaStreamTrack<AudioTrackInterface> {
186 public:
187 static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
188 const std::string& id,
189 MediaStreamTrackInterface::TrackState state,
190 int signal_level,
191 rtc::scoped_refptr<FakeAudioProcessorForStats> processor) {
192 rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
193 new rtc::RefCountedObject<FakeAudioTrackForStats>(
194 id, signal_level, processor));
195 audio_track_stats->set_state(state);
196 return audio_track_stats;
197 }
198
199 FakeAudioTrackForStats(
200 const std::string& id,
201 int signal_level,
202 rtc::scoped_refptr<FakeAudioProcessorForStats> processor)
203 : MediaStreamTrack<AudioTrackInterface>(id),
204 signal_level_(signal_level),
205 processor_(processor) {
206 }
207
208 std::string kind() const override {
209 return MediaStreamTrackInterface::kAudioKind;
210 }
211 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
212 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
213 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
214 bool GetSignalLevel(int* level) override {
215 *level = signal_level_;
216 return true;
217 }
218 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
219 return processor_;
220 }
221
222 private:
223 int signal_level_;
224 rtc::scoped_refptr<FakeAudioProcessorForStats> processor_;
225};
226
227class FakeVideoTrackSourceForStats
228 : public rtc::RefCountedObject<VideoTrackSourceInterface> {
229 public:
230 FakeVideoTrackSourceForStats(VideoTrackSourceInterface::Stats stats)
231 : stats_(stats) {
232 }
233
234 MediaSourceInterface::SourceState state() const override {
235 return MediaSourceInterface::kLive;
236 }
237 bool remote() const override { return false; }
238 void RegisterObserver(ObserverInterface* observer) override {}
239 void UnregisterObserver(ObserverInterface* observer) override {}
nisseacd935b2016-11-11 03:55:13 -0800240 void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
hbos09bc1282016-11-08 06:29:22 -0800241 const rtc::VideoSinkWants& wants) override {}
nisseacd935b2016-11-11 03:55:13 -0800242 void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override {
hbos09bc1282016-11-08 06:29:22 -0800243 }
244 bool is_screencast() const override { return false; }
245 rtc::Optional<bool> needs_denoising() const override {
246 return rtc::Optional<bool>();
247 }
248 bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
249 *stats = stats_;
250 return true;
251 }
252
253 private:
254 VideoTrackSourceInterface::Stats stats_;
255};
256
257class FakeVideoTrackForStats
258 : public MediaStreamTrack<VideoTrackInterface> {
259 public:
260 static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
261 const std::string& id,
262 MediaStreamTrackInterface::TrackState state,
263 rtc::scoped_refptr<VideoTrackSourceInterface> source) {
264 rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
265 new rtc::RefCountedObject<FakeVideoTrackForStats>(id, source));
266 video_track->set_state(state);
267 return video_track;
268 }
269
270 FakeVideoTrackForStats(
271 const std::string& id,
272 rtc::scoped_refptr<VideoTrackSourceInterface> source)
273 : MediaStreamTrack<VideoTrackInterface>(id),
274 source_(source) {
275 }
276
277 std::string kind() const override {
278 return MediaStreamTrackInterface::kVideoKind;
279 }
280 VideoTrackSourceInterface* GetSource() const override {
281 return source_;
282 }
283
284 private:
285 rtc::scoped_refptr<VideoTrackSourceInterface> source_;
286};
287
hbosc82f2e12016-09-05 01:36:50 -0700288class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
hbosd565b732016-08-30 14:04:35 -0700289 public:
hbosc82f2e12016-09-05 01:36:50 -0700290 RTCStatsCollectorTestHelper()
hbosd565b732016-08-30 14:04:35 -0700291 : worker_thread_(rtc::Thread::Current()),
292 network_thread_(rtc::Thread::Current()),
hbos6ded1902016-11-01 01:50:46 -0700293 media_engine_(new cricket::FakeMediaEngine()),
skvlad11a9cbf2016-10-07 11:53:05 -0700294 channel_manager_(
hbos6ded1902016-11-01 01:50:46 -0700295 new cricket::ChannelManager(media_engine_,
skvlad11a9cbf2016-10-07 11:53:05 -0700296 worker_thread_,
297 network_thread_)),
hbosd565b732016-08-30 14:04:35 -0700298 media_controller_(
299 MediaControllerInterface::Create(cricket::MediaConfig(),
300 worker_thread_,
skvlad11a9cbf2016-10-07 11:53:05 -0700301 channel_manager_.get(),
302 &event_log_)),
hbosd565b732016-08-30 14:04:35 -0700303 session_(media_controller_.get()),
304 pc_() {
hbos6ab97ce2016-10-03 14:16:56 -0700305 // Default return values for mocks.
hbos09bc1282016-11-08 06:29:22 -0800306 EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr));
307 EXPECT_CALL(pc_, remote_streams()).WillRepeatedly(Return(nullptr));
hbosd565b732016-08-30 14:04:35 -0700308 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
309 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
310 ReturnRef(data_channels_));
hbos6ded1902016-11-01 01:50:46 -0700311 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
312 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
hbos6ab97ce2016-10-03 14:16:56 -0700313 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
hbosab9f6e42016-10-07 02:18:47 -0700314 EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly(
315 Return(false));
316 EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_))
317 .WillRepeatedly(Return(nullptr));
hbosd565b732016-08-30 14:04:35 -0700318 }
319
hbosfdafab82016-09-14 06:02:13 -0700320 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; }
hbos6ded1902016-11-01 01:50:46 -0700321 rtc::Thread* worker_thread() { return worker_thread_; }
322 rtc::Thread* network_thread() { return network_thread_; }
323 cricket::FakeMediaEngine* media_engine() { return media_engine_; }
hbosd565b732016-08-30 14:04:35 -0700324 MockWebRtcSession& session() { return session_; }
325 MockPeerConnection& pc() { return pc_; }
326 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() {
327 return data_channels_;
328 }
329
330 // SetSessionDescriptionObserver overrides.
331 void OnSuccess() override {}
332 void OnFailure(const std::string& error) override {
333 RTC_NOTREACHED() << error;
334 }
335
336 private:
hbosfdafab82016-09-14 06:02:13 -0700337 rtc::ScopedFakeClock fake_clock_;
hbos09bc1282016-11-08 06:29:22 -0800338 RtcEventLogNullImpl event_log_;
hbosd565b732016-08-30 14:04:35 -0700339 rtc::Thread* const worker_thread_;
340 rtc::Thread* const network_thread_;
hbos6ded1902016-11-01 01:50:46 -0700341 cricket::FakeMediaEngine* media_engine_;
hbosd565b732016-08-30 14:04:35 -0700342 std::unique_ptr<cricket::ChannelManager> channel_manager_;
hbos09bc1282016-11-08 06:29:22 -0800343 std::unique_ptr<MediaControllerInterface> media_controller_;
hbosd565b732016-08-30 14:04:35 -0700344 MockWebRtcSession session_;
345 MockPeerConnection pc_;
346
347 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
348};
349
hbosc82f2e12016-09-05 01:36:50 -0700350class RTCTestStats : public RTCStats {
hbosd565b732016-08-30 14:04:35 -0700351 public:
hbosfc5e0502016-10-06 02:06:10 -0700352 WEBRTC_RTCSTATS_DECL();
353
hbosc82f2e12016-09-05 01:36:50 -0700354 RTCTestStats(const std::string& id, int64_t timestamp_us)
355 : RTCStats(id, timestamp_us),
356 dummy_stat("dummyStat") {}
357
hbosc82f2e12016-09-05 01:36:50 -0700358 RTCStatsMember<int32_t> dummy_stat;
359};
360
hbosfc5e0502016-10-06 02:06:10 -0700361WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats",
362 &dummy_stat);
hbosc82f2e12016-09-05 01:36:50 -0700363
364// Overrides the stats collection to verify thread usage and that the resulting
365// partial reports are merged.
366class FakeRTCStatsCollector : public RTCStatsCollector,
367 public RTCStatsCollectorCallback {
368 public:
369 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
370 PeerConnection* pc,
371 int64_t cache_lifetime_us) {
372 return rtc::scoped_refptr<FakeRTCStatsCollector>(
373 new rtc::RefCountedObject<FakeRTCStatsCollector>(
374 pc, cache_lifetime_us));
375 }
376
377 // RTCStatsCollectorCallback implementation.
378 void OnStatsDelivered(
379 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
380 EXPECT_TRUE(signaling_thread_->IsCurrent());
381 rtc::CritScope cs(&lock_);
382 delivered_report_ = report;
383 }
384
385 void VerifyThreadUsageAndResultsMerging() {
386 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
387 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
388 }
389
390 bool HasVerifiedResults() {
391 EXPECT_TRUE(signaling_thread_->IsCurrent());
392 rtc::CritScope cs(&lock_);
393 if (!delivered_report_)
394 return false;
395 EXPECT_EQ(produced_on_signaling_thread_, 1);
396 EXPECT_EQ(produced_on_worker_thread_, 1);
397 EXPECT_EQ(produced_on_network_thread_, 1);
398
399 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
400 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
401 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
402
403 produced_on_signaling_thread_ = 0;
404 produced_on_worker_thread_ = 0;
405 produced_on_network_thread_ = 0;
406 delivered_report_ = nullptr;
407 return true;
hbosd565b732016-08-30 14:04:35 -0700408 }
409
410 protected:
hbosc82f2e12016-09-05 01:36:50 -0700411 FakeRTCStatsCollector(
412 PeerConnection* pc,
413 int64_t cache_lifetime)
414 : RTCStatsCollector(pc, cache_lifetime),
415 signaling_thread_(pc->session()->signaling_thread()),
416 worker_thread_(pc->session()->worker_thread()),
417 network_thread_(pc->session()->network_thread()) {
418 }
419
420 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
421 EXPECT_TRUE(signaling_thread_->IsCurrent());
422 {
423 rtc::CritScope cs(&lock_);
424 EXPECT_FALSE(delivered_report_);
425 ++produced_on_signaling_thread_;
426 }
427
428 rtc::scoped_refptr<RTCStatsReport> signaling_report =
hbos6ded1902016-11-01 01:50:46 -0700429 RTCStatsReport::Create(0);
hbosc82f2e12016-09-05 01:36:50 -0700430 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
431 new RTCTestStats("SignalingThreadStats", timestamp_us)));
432 AddPartialResults(signaling_report);
433 }
434 void ProducePartialResultsOnWorkerThread(int64_t timestamp_us) override {
435 EXPECT_TRUE(worker_thread_->IsCurrent());
436 {
437 rtc::CritScope cs(&lock_);
438 EXPECT_FALSE(delivered_report_);
439 ++produced_on_worker_thread_;
440 }
441
hbos6ded1902016-11-01 01:50:46 -0700442 rtc::scoped_refptr<RTCStatsReport> worker_report =
443 RTCStatsReport::Create(0);
hbosc82f2e12016-09-05 01:36:50 -0700444 worker_report->AddStats(std::unique_ptr<const RTCStats>(
445 new RTCTestStats("WorkerThreadStats", timestamp_us)));
446 AddPartialResults(worker_report);
447 }
448 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
449 EXPECT_TRUE(network_thread_->IsCurrent());
450 {
451 rtc::CritScope cs(&lock_);
452 EXPECT_FALSE(delivered_report_);
453 ++produced_on_network_thread_;
454 }
455
456 rtc::scoped_refptr<RTCStatsReport> network_report =
hbos6ded1902016-11-01 01:50:46 -0700457 RTCStatsReport::Create(0);
hbosc82f2e12016-09-05 01:36:50 -0700458 network_report->AddStats(std::unique_ptr<const RTCStats>(
459 new RTCTestStats("NetworkThreadStats", timestamp_us)));
460 AddPartialResults(network_report);
461 }
462
463 private:
464 rtc::Thread* const signaling_thread_;
465 rtc::Thread* const worker_thread_;
466 rtc::Thread* const network_thread_;
467
468 rtc::CriticalSection lock_;
469 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
470 int produced_on_signaling_thread_ = 0;
471 int produced_on_worker_thread_ = 0;
472 int produced_on_network_thread_ = 0;
hbosd565b732016-08-30 14:04:35 -0700473};
474
hbosc82f2e12016-09-05 01:36:50 -0700475class StatsCallback : public RTCStatsCollectorCallback {
476 public:
477 static rtc::scoped_refptr<StatsCallback> Create(
478 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
479 return rtc::scoped_refptr<StatsCallback>(
480 new rtc::RefCountedObject<StatsCallback>(report_ptr));
481 }
482
483 void OnStatsDelivered(
484 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
485 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
486 report_ = report;
487 if (report_ptr_)
488 *report_ptr_ = report_;
489 }
490
491 rtc::scoped_refptr<const RTCStatsReport> report() const {
492 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
493 return report_;
494 }
495
496 protected:
497 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
498 : report_ptr_(report_ptr) {}
499
500 private:
501 rtc::ThreadChecker thread_checker_;
502 rtc::scoped_refptr<const RTCStatsReport> report_;
503 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
504};
505
506class RTCStatsCollectorTest : public testing::Test {
507 public:
508 RTCStatsCollectorTest()
509 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
510 collector_(RTCStatsCollector::Create(
511 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
512 }
513
514 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
515 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
516 collector_->GetStatsReport(callback);
517 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
hboscc555c52016-10-18 12:48:31 -0700518 int64_t after = rtc::TimeUTCMicros();
519 for (const RTCStats& stats : *callback->report()) {
520 EXPECT_LE(stats.timestamp_us(), after);
521 }
hbosc82f2e12016-09-05 01:36:50 -0700522 return callback->report();
523 }
524
hbosc47a0c32016-10-11 14:54:49 -0700525 const RTCIceCandidateStats* ExpectReportContainsCandidate(
hbosab9f6e42016-10-07 02:18:47 -0700526 const rtc::scoped_refptr<const RTCStatsReport>& report,
527 const cricket::Candidate& candidate,
528 bool is_local) {
hbosc47a0c32016-10-11 14:54:49 -0700529 const RTCStats* stats = report->Get("RTCIceCandidate_" + candidate.id());
hbosab9f6e42016-10-07 02:18:47 -0700530 EXPECT_TRUE(stats);
531 const RTCIceCandidateStats* candidate_stats;
532 if (is_local)
533 candidate_stats = &stats->cast_to<RTCLocalIceCandidateStats>();
534 else
535 candidate_stats = &stats->cast_to<RTCRemoteIceCandidateStats>();
536 EXPECT_EQ(*candidate_stats->ip, candidate.address().ipaddr().ToString());
537 EXPECT_EQ(*candidate_stats->port,
538 static_cast<int32_t>(candidate.address().port()));
539 EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
540 EXPECT_EQ(*candidate_stats->candidate_type,
hboscc555c52016-10-18 12:48:31 -0700541 CandidateTypeToRTCIceCandidateTypeForTesting(candidate.type()));
hbosab9f6e42016-10-07 02:18:47 -0700542 EXPECT_EQ(*candidate_stats->priority,
543 static_cast<int32_t>(candidate.priority()));
544 // TODO(hbos): Define candidate_stats->url. crbug.com/632723
545 EXPECT_FALSE(candidate_stats->url.is_defined());
hbosc47a0c32016-10-11 14:54:49 -0700546 return candidate_stats;
547 }
548
549 void ExpectReportContainsCandidatePair(
550 const rtc::scoped_refptr<const RTCStatsReport>& report,
551 const cricket::TransportStats& transport_stats) {
552 for (const auto& channel_stats : transport_stats.channel_stats) {
553 for (const cricket::ConnectionInfo& info :
554 channel_stats.connection_infos) {
555 const std::string& id = "RTCIceCandidatePair_" +
556 info.local_candidate.id() + "_" + info.remote_candidate.id();
557 const RTCStats* stats = report->Get(id);
hbos2fa7c672016-10-24 04:00:05 -0700558 ASSERT_TRUE(stats);
hbosc47a0c32016-10-11 14:54:49 -0700559 const RTCIceCandidatePairStats& candidate_pair_stats =
560 stats->cast_to<RTCIceCandidatePairStats>();
561
562 // TODO(hbos): Define all the undefined |candidate_pair_stats| stats.
563 // The EXPECT_FALSE are for the undefined stats, see also todos listed
hbos5d79a7c2016-10-24 09:27:10 -0700564 // in rtcstats_objects.h. crbug.com/633550
hbosc47a0c32016-10-11 14:54:49 -0700565 EXPECT_FALSE(candidate_pair_stats.transport_id.is_defined());
566 const RTCIceCandidateStats* local_candidate =
567 ExpectReportContainsCandidate(report, info.local_candidate, true);
568 EXPECT_EQ(*candidate_pair_stats.local_candidate_id,
569 local_candidate->id());
570 const RTCIceCandidateStats* remote_candidate =
571 ExpectReportContainsCandidate(report, info.remote_candidate, false);
572 EXPECT_EQ(*candidate_pair_stats.remote_candidate_id,
573 remote_candidate->id());
574
575 EXPECT_FALSE(candidate_pair_stats.state.is_defined());
576 EXPECT_FALSE(candidate_pair_stats.priority.is_defined());
577 EXPECT_FALSE(candidate_pair_stats.nominated.is_defined());
578 EXPECT_EQ(*candidate_pair_stats.writable, info.writable);
579 EXPECT_FALSE(candidate_pair_stats.readable.is_defined());
580 EXPECT_EQ(*candidate_pair_stats.bytes_sent,
581 static_cast<uint64_t>(info.sent_total_bytes));
582 EXPECT_EQ(*candidate_pair_stats.bytes_received,
583 static_cast<uint64_t>(info.recv_total_bytes));
584 EXPECT_FALSE(candidate_pair_stats.total_rtt.is_defined());
585 EXPECT_EQ(*candidate_pair_stats.current_rtt,
586 static_cast<double>(info.rtt) / 1000.0);
587 EXPECT_FALSE(
588 candidate_pair_stats.available_outgoing_bitrate.is_defined());
589 EXPECT_FALSE(
590 candidate_pair_stats.available_incoming_bitrate.is_defined());
591 EXPECT_FALSE(candidate_pair_stats.requests_received.is_defined());
592 EXPECT_EQ(*candidate_pair_stats.requests_sent,
593 static_cast<uint64_t>(info.sent_ping_requests_total));
594 EXPECT_EQ(*candidate_pair_stats.responses_received,
595 static_cast<uint64_t>(info.recv_ping_responses));
596 EXPECT_EQ(*candidate_pair_stats.responses_sent,
597 static_cast<uint64_t>(info.sent_ping_responses));
598 EXPECT_FALSE(
599 candidate_pair_stats.retransmissions_received.is_defined());
600 EXPECT_FALSE(candidate_pair_stats.retransmissions_sent.is_defined());
601 EXPECT_FALSE(
602 candidate_pair_stats.consent_requests_received.is_defined());
603 EXPECT_FALSE(candidate_pair_stats.consent_requests_sent.is_defined());
604 EXPECT_FALSE(
605 candidate_pair_stats.consent_responses_received.is_defined());
606 EXPECT_FALSE(candidate_pair_stats.consent_responses_sent.is_defined());
607 }
608 }
hbosab9f6e42016-10-07 02:18:47 -0700609 }
610
hbos6ab97ce2016-10-03 14:16:56 -0700611 void ExpectReportContainsCertificateInfo(
612 const rtc::scoped_refptr<const RTCStatsReport>& report,
613 const CertificateInfo& cert_info) {
614 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
615 const RTCStats* stats = report->Get(
616 "RTCCertificate_" + cert_info.fingerprints[i]);
hbos2fa7c672016-10-24 04:00:05 -0700617 ASSERT_TRUE(stats);
hbos6ab97ce2016-10-03 14:16:56 -0700618 const RTCCertificateStats& cert_stats =
619 stats->cast_to<const RTCCertificateStats>();
620 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
621 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
622 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
623 if (i + 1 < cert_info.fingerprints.size()) {
624 EXPECT_EQ(*cert_stats.issuer_certificate_id,
625 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
626 } else {
627 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
628 }
629 }
630 }
631
hbos2fa7c672016-10-24 04:00:05 -0700632 void ExpectReportContainsTransportStats(
633 const rtc::scoped_refptr<const RTCStatsReport>& report,
634 const cricket::TransportStats& transport,
635 const CertificateInfo* local_certinfo,
636 const CertificateInfo* remote_certinfo) {
637 std::string rtcp_transport_stats_id;
638 for (const auto& channel_stats : transport.channel_stats) {
639 if (channel_stats.component == cricket::ICE_CANDIDATE_COMPONENT_RTCP) {
640 rtcp_transport_stats_id = "RTCTransport_" + transport.transport_name +
641 "_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP);
642 }
643 }
644 for (const auto& channel_stats : transport.channel_stats) {
645 const cricket::ConnectionInfo* best_connection_info = nullptr;
646 const RTCStats* stats = report->Get(
647 "RTCTransport_" + transport.transport_name + "_" +
648 rtc::ToString<>(channel_stats.component));
649 ASSERT_TRUE(stats);
650 const RTCTransportStats& transport_stats =
651 stats->cast_to<const RTCTransportStats>();
652 uint64_t bytes_sent = 0;
653 uint64_t bytes_received = 0;
654 for (const cricket::ConnectionInfo& info :
655 channel_stats.connection_infos) {
656 bytes_sent += info.sent_total_bytes;
657 bytes_received += info.recv_total_bytes;
658 if (info.best_connection)
659 best_connection_info = &info;
660 }
661 EXPECT_EQ(*transport_stats.bytes_sent, bytes_sent);
662 EXPECT_EQ(*transport_stats.bytes_received, bytes_received);
663 if (best_connection_info) {
664 EXPECT_EQ(*transport_stats.active_connection, true);
665 // TODO(hbos): Instead of testing how the ID looks, test that the
666 // corresponding pair's IP addresses are equal to the IP addresses of
667 // the |best_connection_info| data. crbug.com/653873
668 EXPECT_EQ(*transport_stats.selected_candidate_pair_id,
669 "RTCIceCandidatePair_" +
670 best_connection_info->local_candidate.id() + "_" +
671 best_connection_info->remote_candidate.id());
672 EXPECT_TRUE(report->Get(*transport_stats.selected_candidate_pair_id));
673 } else {
674 EXPECT_EQ(*transport_stats.active_connection, false);
675 EXPECT_FALSE(transport_stats.selected_candidate_pair_id.is_defined());
676 }
677 if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP &&
678 !rtcp_transport_stats_id.empty()) {
679 EXPECT_EQ(*transport_stats.rtcp_transport_stats_id,
680 rtcp_transport_stats_id);
681 } else {
682 EXPECT_FALSE(transport_stats.rtcp_transport_stats_id.is_defined());
683 }
684 if (local_certinfo && remote_certinfo) {
685 EXPECT_EQ(*transport_stats.local_certificate_id,
686 "RTCCertificate_" + local_certinfo->fingerprints[0]);
687 EXPECT_EQ(*transport_stats.remote_certificate_id,
688 "RTCCertificate_" + remote_certinfo->fingerprints[0]);
689 EXPECT_TRUE(report->Get(*transport_stats.local_certificate_id));
690 EXPECT_TRUE(report->Get(*transport_stats.remote_certificate_id));
691 } else {
692 EXPECT_FALSE(transport_stats.local_certificate_id.is_defined());
693 EXPECT_FALSE(transport_stats.remote_certificate_id.is_defined());
694 }
695 }
696 }
697
hboscc555c52016-10-18 12:48:31 -0700698 void ExpectReportContainsDataChannel(
699 const rtc::scoped_refptr<const RTCStatsReport>& report,
700 const DataChannel& data_channel) {
701 const RTCStats* stats = report->Get("RTCDataChannel_" +
702 rtc::ToString<>(data_channel.id()));
703 EXPECT_TRUE(stats);
704 const RTCDataChannelStats& data_channel_stats =
705 stats->cast_to<const RTCDataChannelStats>();
706 EXPECT_EQ(*data_channel_stats.label, data_channel.label());
707 EXPECT_EQ(*data_channel_stats.protocol, data_channel.protocol());
708 EXPECT_EQ(*data_channel_stats.datachannelid, data_channel.id());
709 EXPECT_EQ(*data_channel_stats.state,
710 DataStateToRTCDataChannelStateForTesting(data_channel.state()));
711 EXPECT_EQ(*data_channel_stats.messages_sent, data_channel.messages_sent());
712 EXPECT_EQ(*data_channel_stats.bytes_sent, data_channel.bytes_sent());
713 EXPECT_EQ(*data_channel_stats.messages_received,
714 data_channel.messages_received());
715 EXPECT_EQ(*data_channel_stats.bytes_received,
716 data_channel.bytes_received());
717 }
718
hbosc82f2e12016-09-05 01:36:50 -0700719 protected:
720 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
721 rtc::scoped_refptr<RTCStatsCollector> collector_;
722};
723
724TEST_F(RTCStatsCollectorTest, SingleCallback) {
725 rtc::scoped_refptr<const RTCStatsReport> result;
726 collector_->GetStatsReport(StatsCallback::Create(&result));
727 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
728}
729
730TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
731 rtc::scoped_refptr<const RTCStatsReport> a;
732 rtc::scoped_refptr<const RTCStatsReport> b;
733 rtc::scoped_refptr<const RTCStatsReport> c;
734 collector_->GetStatsReport(StatsCallback::Create(&a));
735 collector_->GetStatsReport(StatsCallback::Create(&b));
736 collector_->GetStatsReport(StatsCallback::Create(&c));
737 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
738 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
739 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
740 EXPECT_EQ(a.get(), b.get());
741 EXPECT_EQ(b.get(), c.get());
742}
743
744TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700745 // Caching should ensure |a| and |b| are the same report.
hbosc82f2e12016-09-05 01:36:50 -0700746 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
747 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700748 EXPECT_EQ(a.get(), b.get());
749 // Invalidate cache by clearing it.
hbosc82f2e12016-09-05 01:36:50 -0700750 collector_->ClearCachedStatsReport();
751 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700752 EXPECT_NE(b.get(), c.get());
753 // Invalidate cache by advancing time.
hbosfdafab82016-09-14 06:02:13 -0700754 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700755 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700756 EXPECT_TRUE(d);
757 EXPECT_NE(c.get(), d.get());
758}
759
hbosc82f2e12016-09-05 01:36:50 -0700760TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
hbosc82f2e12016-09-05 01:36:50 -0700761 rtc::scoped_refptr<const RTCStatsReport> a;
762 rtc::scoped_refptr<const RTCStatsReport> b;
763 rtc::scoped_refptr<const RTCStatsReport> c;
764 collector_->GetStatsReport(StatsCallback::Create(&a));
765 collector_->GetStatsReport(StatsCallback::Create(&b));
766 // Cache is invalidated after 50 ms.
hbosfdafab82016-09-14 06:02:13 -0700767 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700768 collector_->GetStatsReport(StatsCallback::Create(&c));
769 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
770 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
771 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
772 EXPECT_EQ(a.get(), b.get());
773 // The act of doing |AdvanceTime| processes all messages. If this was not the
774 // case we might not require |c| to be fresher than |b|.
775 EXPECT_NE(c.get(), b.get());
776}
777
hbos6ab97ce2016-10-03 14:16:56 -0700778TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
779 std::unique_ptr<CertificateInfo> local_certinfo =
780 CreateFakeCertificateAndInfoFromDers(
781 std::vector<std::string>({ "(local) single certificate" }));
782 std::unique_ptr<CertificateInfo> remote_certinfo =
783 CreateFakeCertificateAndInfoFromDers(
784 std::vector<std::string>({ "(remote) single certificate" }));
785
786 // Mock the session to return the local and remote certificates.
787 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
788 [this](SessionStats* stats) {
789 stats->transport_stats["transport"].transport_name = "transport";
790 return true;
791 }));
792 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
793 Invoke([this, &local_certinfo](const std::string& transport_name,
794 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
795 if (transport_name == "transport") {
796 *certificate = local_certinfo->certificate;
797 return true;
798 }
799 return false;
800 }));
801 EXPECT_CALL(test_->session(),
802 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
803 [this, &remote_certinfo](const std::string& transport_name) {
804 if (transport_name == "transport")
805 return remote_certinfo->certificate->ssl_certificate().GetReference();
806 return static_cast<rtc::SSLCertificate*>(nullptr);
807 }));
808
809 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
810 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
811 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
812}
813
hbos0adb8282016-11-23 02:32:06 -0800814TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
815 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
816 cricket::VoiceChannel voice_channel(
817 test_->worker_thread(), test_->network_thread(), test_->media_engine(),
818 voice_media_channel, nullptr, "VoiceContentName", false);
819
820 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
821 cricket::VideoChannel video_channel(
822 test_->worker_thread(), test_->network_thread(), video_media_channel,
823 nullptr, "VideoContentName", false);
824
825 // Audio
826 cricket::VoiceMediaInfo voice_media_info;
827
828 RtpCodecParameters inbound_audio_codec;
829 inbound_audio_codec.payload_type = 1;
830 inbound_audio_codec.mime_type = "opus";
831 inbound_audio_codec.clock_rate = 1337;
832 voice_media_info.receive_codecs.insert(
833 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec));
834
835 RtpCodecParameters outbound_audio_codec;
836 outbound_audio_codec.payload_type = 2;
837 outbound_audio_codec.mime_type = "isac";
838 outbound_audio_codec.clock_rate = 1338;
839 voice_media_info.send_codecs.insert(
840 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec));
841
842 EXPECT_CALL(*voice_media_channel, GetStats(_))
843 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
844
845 // Video
846 cricket::VideoMediaInfo video_media_info;
847
848 RtpCodecParameters inbound_video_codec;
849 inbound_video_codec.payload_type = 3;
850 inbound_video_codec.mime_type = "H264";
851 inbound_video_codec.clock_rate = 1339;
852 video_media_info.receive_codecs.insert(
853 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec));
854
855 RtpCodecParameters outbound_video_codec;
856 outbound_video_codec.payload_type = 4;
857 outbound_video_codec.mime_type = "VP8";
858 outbound_video_codec.clock_rate = 1340;
859 video_media_info.send_codecs.insert(
860 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec));
861
862 EXPECT_CALL(*video_media_channel, GetStats(_))
863 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
864
865 SessionStats session_stats;
866 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
867 session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
868 session_stats.transport_stats["TransportName"].transport_name =
869 "TransportName";
870
871 EXPECT_CALL(test_->session(), GetTransportStats(_))
872 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
873 EXPECT_CALL(test_->session(), voice_channel())
874 .WillRepeatedly(Return(&voice_channel));
875 EXPECT_CALL(test_->session(), video_channel())
876 .WillRepeatedly(Return(&video_channel));
877
878 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
879
880 RTCCodecStats expected_inbound_audio_codec(
881 "RTCCodec_InboundAudio_1", report->timestamp_us());
882 expected_inbound_audio_codec.payload_type = 1;
883 expected_inbound_audio_codec.codec = "audio/opus";
884 expected_inbound_audio_codec.clock_rate = 1337;
885
886 RTCCodecStats expected_outbound_audio_codec(
887 "RTCCodec_OutboundAudio_2", report->timestamp_us());
888 expected_outbound_audio_codec.payload_type = 2;
889 expected_outbound_audio_codec.codec = "audio/isac";
890 expected_outbound_audio_codec.clock_rate = 1338;
891
892 RTCCodecStats expected_inbound_video_codec(
893 "RTCCodec_InboundVideo_3", report->timestamp_us());
894 expected_inbound_video_codec.payload_type = 3;
895 expected_inbound_video_codec.codec = "video/H264";
896 expected_inbound_video_codec.clock_rate = 1339;
897
898 RTCCodecStats expected_outbound_video_codec(
899 "RTCCodec_OutboundVideo_4", report->timestamp_us());
900 expected_outbound_video_codec.payload_type = 4;
901 expected_outbound_video_codec.codec = "video/VP8";
902 expected_outbound_video_codec.clock_rate = 1340;
903
904 ASSERT(report->Get(expected_inbound_audio_codec.id()));
905 EXPECT_EQ(expected_inbound_audio_codec,
906 report->Get(expected_inbound_audio_codec.id())->cast_to<
907 RTCCodecStats>());
908
909 ASSERT(report->Get(expected_outbound_audio_codec.id()));
910 EXPECT_EQ(expected_outbound_audio_codec,
911 report->Get(expected_outbound_audio_codec.id())->cast_to<
912 RTCCodecStats>());
913
914 ASSERT(report->Get(expected_inbound_video_codec.id()));
915 EXPECT_EQ(expected_inbound_video_codec,
916 report->Get(expected_inbound_video_codec.id())->cast_to<
917 RTCCodecStats>());
918
919 ASSERT(report->Get(expected_outbound_video_codec.id()));
920 EXPECT_EQ(expected_outbound_video_codec,
921 report->Get(expected_outbound_video_codec.id())->cast_to<
922 RTCCodecStats>());
923}
924
hbos6ab97ce2016-10-03 14:16:56 -0700925TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
926 std::unique_ptr<CertificateInfo> audio_local_certinfo =
927 CreateFakeCertificateAndInfoFromDers(
928 std::vector<std::string>({ "(local) audio" }));
929 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
930 audio_local_certinfo->ders);
931 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
932 CreateFakeCertificateAndInfoFromDers(
933 std::vector<std::string>({ "(remote) audio" }));
934 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
935 audio_remote_certinfo->ders);
936
937 std::unique_ptr<CertificateInfo> video_local_certinfo =
938 CreateFakeCertificateAndInfoFromDers(
939 std::vector<std::string>({ "(local) video" }));
940 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
941 video_local_certinfo->ders);
942 std::unique_ptr<CertificateInfo> video_remote_certinfo =
943 CreateFakeCertificateAndInfoFromDers(
944 std::vector<std::string>({ "(remote) video" }));
945 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
946 video_remote_certinfo->ders);
947
948 // Mock the session to return the local and remote certificates.
949 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
950 [this](SessionStats* stats) {
951 stats->transport_stats["audio"].transport_name = "audio";
952 stats->transport_stats["video"].transport_name = "video";
953 return true;
954 }));
955 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
956 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
957 const std::string& transport_name,
958 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
959 if (transport_name == "audio") {
960 *certificate = audio_local_certinfo->certificate;
961 return true;
962 }
963 if (transport_name == "video") {
964 *certificate = video_local_certinfo->certificate;
965 return true;
966 }
967 return false;
968 }));
969 EXPECT_CALL(test_->session(),
970 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
971 [this, &audio_remote_certinfo, &video_remote_certinfo](
972 const std::string& transport_name) {
973 if (transport_name == "audio") {
974 return audio_remote_certinfo->certificate->ssl_certificate()
975 .GetReference();
976 }
977 if (transport_name == "video") {
978 return video_remote_certinfo->certificate->ssl_certificate()
979 .GetReference();
980 }
981 return static_cast<rtc::SSLCertificate*>(nullptr);
982 }));
983
984 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
985 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
986 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
987 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
988 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
989}
990
991TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
992 std::vector<std::string> local_ders;
993 local_ders.push_back("(local) this");
994 local_ders.push_back("(local) is");
995 local_ders.push_back("(local) a");
996 local_ders.push_back("(local) chain");
997 std::unique_ptr<CertificateInfo> local_certinfo =
998 CreateFakeCertificateAndInfoFromDers(local_ders);
999 std::vector<std::string> remote_ders;
1000 remote_ders.push_back("(remote) this");
1001 remote_ders.push_back("(remote) is");
1002 remote_ders.push_back("(remote) another");
1003 remote_ders.push_back("(remote) chain");
1004 std::unique_ptr<CertificateInfo> remote_certinfo =
1005 CreateFakeCertificateAndInfoFromDers(remote_ders);
1006
1007 // Mock the session to return the local and remote certificates.
1008 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1009 [this](SessionStats* stats) {
1010 stats->transport_stats["transport"].transport_name = "transport";
1011 return true;
1012 }));
1013 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
1014 Invoke([this, &local_certinfo](const std::string& transport_name,
1015 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
1016 if (transport_name == "transport") {
1017 *certificate = local_certinfo->certificate;
1018 return true;
1019 }
1020 return false;
1021 }));
1022 EXPECT_CALL(test_->session(),
1023 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
1024 [this, &remote_certinfo](const std::string& transport_name) {
1025 if (transport_name == "transport")
1026 return remote_certinfo->certificate->ssl_certificate().GetReference();
1027 return static_cast<rtc::SSLCertificate*>(nullptr);
1028 }));
1029
1030 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1031 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
1032 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
1033}
1034
hboscc555c52016-10-18 12:48:31 -07001035TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
1036 test_->data_channels().push_back(
1037 new MockDataChannel(0, DataChannelInterface::kConnecting));
1038 test_->data_channels().push_back(
1039 new MockDataChannel(1, DataChannelInterface::kOpen));
1040 test_->data_channels().push_back(
1041 new MockDataChannel(2, DataChannelInterface::kClosing));
1042 test_->data_channels().push_back(
1043 new MockDataChannel(3, DataChannelInterface::kClosed));
1044
1045 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1046 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
1047 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
1048 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
1049 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
1050
1051 test_->data_channels().clear();
1052 test_->data_channels().push_back(
1053 new MockDataChannel(0, DataChannelInterface::kConnecting,
1054 1, 2, 3, 4));
1055 test_->data_channels().push_back(
1056 new MockDataChannel(1, DataChannelInterface::kOpen,
1057 5, 6, 7, 8));
1058 test_->data_channels().push_back(
1059 new MockDataChannel(2, DataChannelInterface::kClosing,
1060 9, 10, 11, 12));
1061 test_->data_channels().push_back(
1062 new MockDataChannel(3, DataChannelInterface::kClosed,
1063 13, 14, 15, 16));
1064
1065 collector_->ClearCachedStatsReport();
1066 report = GetStatsReport();
1067 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
1068 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
1069 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
1070 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
1071}
1072
hbosab9f6e42016-10-07 02:18:47 -07001073TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
1074 // Candidates in the first transport stats.
1075 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
1076 "1.2.3.4", 5,
1077 "a_local_host's protocol",
1078 cricket::LOCAL_PORT_TYPE,
1079 0);
1080 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
1081 "6.7.8.9", 10,
1082 "remote_srflx's protocol",
1083 cricket::STUN_PORT_TYPE,
1084 1);
1085 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
1086 "11.12.13.14", 15,
1087 "a_local_prflx's protocol",
1088 cricket::PRFLX_PORT_TYPE,
1089 2);
1090 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
1091 "16.17.18.19", 20,
1092 "a_remote_relay's protocol",
1093 cricket::RELAY_PORT_TYPE,
1094 3);
1095 // Candidates in the second transport stats.
1096 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate(
1097 "42.42.42.42", 42,
1098 "b_local's protocol",
1099 cricket::LOCAL_PORT_TYPE,
1100 42);
1101 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
1102 "42.42.42.42", 42,
1103 "b_remote's protocol",
1104 cricket::LOCAL_PORT_TYPE,
1105 42);
1106
1107 SessionStats session_stats;
1108
1109 cricket::TransportChannelStats a_transport_channel_stats;
1110 a_transport_channel_stats.connection_infos.push_back(
1111 cricket::ConnectionInfo());
1112 a_transport_channel_stats.connection_infos[0].local_candidate =
1113 *a_local_host.get();
1114 a_transport_channel_stats.connection_infos[0].remote_candidate =
1115 *a_remote_srflx.get();
1116 a_transport_channel_stats.connection_infos.push_back(
1117 cricket::ConnectionInfo());
1118 a_transport_channel_stats.connection_infos[1].local_candidate =
1119 *a_local_prflx.get();
1120 a_transport_channel_stats.connection_infos[1].remote_candidate =
1121 *a_remote_relay.get();
1122 session_stats.transport_stats["a"].channel_stats.push_back(
1123 a_transport_channel_stats);
1124
1125 cricket::TransportChannelStats b_transport_channel_stats;
1126 b_transport_channel_stats.connection_infos.push_back(
1127 cricket::ConnectionInfo());
1128 b_transport_channel_stats.connection_infos[0].local_candidate =
1129 *b_local.get();
1130 b_transport_channel_stats.connection_infos[0].remote_candidate =
1131 *b_remote.get();
1132 session_stats.transport_stats["b"].channel_stats.push_back(
1133 b_transport_channel_stats);
1134
1135 // Mock the session to return the desired candidates.
1136 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1137 [this, &session_stats](SessionStats* stats) {
1138 *stats = session_stats;
1139 return true;
1140 }));
1141
1142 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1143 ExpectReportContainsCandidate(report, *a_local_host.get(), true);
1144 ExpectReportContainsCandidate(report, *a_remote_srflx.get(), false);
1145 ExpectReportContainsCandidate(report, *a_local_prflx.get(), true);
1146 ExpectReportContainsCandidate(report, *a_remote_relay.get(), false);
1147 ExpectReportContainsCandidate(report, *b_local.get(), true);
1148 ExpectReportContainsCandidate(report, *b_remote.get(), false);
1149}
1150
hbosc47a0c32016-10-11 14:54:49 -07001151TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
1152 std::unique_ptr<cricket::Candidate> local_candidate = CreateFakeCandidate(
1153 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1154 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
1155 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1156
1157 SessionStats session_stats;
1158
1159 cricket::ConnectionInfo connection_info;
1160 connection_info.local_candidate = *local_candidate.get();
1161 connection_info.remote_candidate = *remote_candidate.get();
1162 connection_info.writable = true;
1163 connection_info.sent_total_bytes = 42;
1164 connection_info.recv_total_bytes = 1234;
1165 connection_info.rtt = 1337;
1166 connection_info.sent_ping_requests_total = 1010;
1167 connection_info.recv_ping_responses = 4321;
1168 connection_info.sent_ping_responses = 1000;
1169
1170 cricket::TransportChannelStats transport_channel_stats;
1171 transport_channel_stats.connection_infos.push_back(connection_info);
1172 session_stats.transport_stats["transport"].transport_name = "transport";
1173 session_stats.transport_stats["transport"].channel_stats.push_back(
1174 transport_channel_stats);
1175
1176 // Mock the session to return the desired candidates.
1177 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1178 [this, &session_stats](SessionStats* stats) {
1179 *stats = session_stats;
1180 return true;
1181 }));
1182
1183 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1184 ExpectReportContainsCandidatePair(
1185 report, session_stats.transport_stats["transport"]);
1186}
1187
hbosd565b732016-08-30 14:04:35 -07001188TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosd565b732016-08-30 14:04:35 -07001189 {
hbos82ebe022016-11-14 01:41:09 -08001190 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1191 RTCPeerConnectionStats expected("RTCPeerConnection",
1192 report->timestamp_us());
1193 expected.data_channels_opened = 0;
1194 expected.data_channels_closed = 0;
1195 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1196 EXPECT_EQ(expected,
1197 report->Get("RTCPeerConnection")->cast_to<
1198 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001199 }
1200
hbos82ebe022016-11-14 01:41:09 -08001201 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create(
1202 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit());
1203 test_->pc().SignalDataChannelCreated(dummy_channel_a.get());
1204 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create(
1205 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit());
1206 test_->pc().SignalDataChannelCreated(dummy_channel_b.get());
hbosd565b732016-08-30 14:04:35 -07001207
hbos82ebe022016-11-14 01:41:09 -08001208 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1209 // Closing a channel that is not opened should not affect the counts.
1210 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1211
hbosd565b732016-08-30 14:04:35 -07001212 {
hbos82ebe022016-11-14 01:41:09 -08001213 collector_->ClearCachedStatsReport();
1214 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1215 RTCPeerConnectionStats expected("RTCPeerConnection",
1216 report->timestamp_us());
1217 expected.data_channels_opened = 1;
1218 expected.data_channels_closed = 0;
1219 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1220 EXPECT_EQ(expected,
1221 report->Get("RTCPeerConnection")->cast_to<
1222 RTCPeerConnectionStats>());
1223 }
1224
1225 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1226 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1227
1228 {
1229 collector_->ClearCachedStatsReport();
1230 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1231 RTCPeerConnectionStats expected("RTCPeerConnection",
1232 report->timestamp_us());
1233 expected.data_channels_opened = 2;
1234 expected.data_channels_closed = 1;
1235 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1236 EXPECT_EQ(expected,
1237 report->Get("RTCPeerConnection")->cast_to<
1238 RTCPeerConnectionStats>());
hbosd565b732016-08-30 14:04:35 -07001239 }
1240}
1241
hbos09bc1282016-11-08 06:29:22 -08001242TEST_F(RTCStatsCollectorTest,
1243 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
1244 rtc::scoped_refptr<StreamCollection> local_streams =
1245 StreamCollection::Create();
1246 rtc::scoped_refptr<StreamCollection> remote_streams =
1247 StreamCollection::Create();
1248 EXPECT_CALL(test_->pc(), local_streams())
1249 .WillRepeatedly(Return(local_streams));
1250 EXPECT_CALL(test_->pc(), remote_streams())
1251 .WillRepeatedly(Return(remote_streams));
1252
1253 rtc::scoped_refptr<MediaStream> local_stream =
1254 MediaStream::Create("LocalStreamLabel");
1255 local_streams->AddStream(local_stream);
1256 rtc::scoped_refptr<MediaStream> remote_stream =
1257 MediaStream::Create("RemoteStreamLabel");
1258 remote_streams->AddStream(remote_stream);
1259
1260 // Local audio track
1261 AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats;
1262 local_audio_processor_stats.echo_return_loss = 42;
1263 local_audio_processor_stats.echo_return_loss_enhancement = 52;
1264 rtc::scoped_refptr<FakeAudioTrackForStats> local_audio_track =
1265 FakeAudioTrackForStats::Create(
1266 "LocalAudioTrackID",
1267 MediaStreamTrackInterface::TrackState::kEnded,
1268 32767,
1269 new FakeAudioProcessorForStats(local_audio_processor_stats));
1270 local_stream->AddTrack(local_audio_track);
1271
1272 // Remote audio track
1273 AudioProcessorInterface::AudioProcessorStats remote_audio_processor_stats;
1274 remote_audio_processor_stats.echo_return_loss = 13;
1275 remote_audio_processor_stats.echo_return_loss_enhancement = 37;
1276 rtc::scoped_refptr<FakeAudioTrackForStats> remote_audio_track =
1277 FakeAudioTrackForStats::Create(
1278 "RemoteAudioTrackID",
1279 MediaStreamTrackInterface::TrackState::kLive,
1280 0,
1281 new FakeAudioProcessorForStats(remote_audio_processor_stats));
1282 remote_stream->AddTrack(remote_audio_track);
1283
1284 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1285
1286 RTCMediaStreamStats expected_local_stream(
1287 "RTCMediaStream_LocalStreamLabel", report->timestamp_us());
1288 expected_local_stream.stream_identifier = local_stream->label();
1289 expected_local_stream.track_ids = std::vector<std::string>();
1290 expected_local_stream.track_ids->push_back(
1291 "RTCMediaStreamTrack_LocalAudioTrackID");
1292 EXPECT_TRUE(report->Get(expected_local_stream.id()));
1293 EXPECT_EQ(expected_local_stream,
1294 report->Get(expected_local_stream.id())->cast_to<
1295 RTCMediaStreamStats>());
1296
1297 RTCMediaStreamStats expected_remote_stream(
1298 "RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
1299 expected_remote_stream.stream_identifier = remote_stream->label();
1300 expected_remote_stream.track_ids = std::vector<std::string>();
1301 expected_remote_stream.track_ids->push_back(
1302 "RTCMediaStreamTrack_RemoteAudioTrackID");
1303 EXPECT_TRUE(report->Get(expected_remote_stream.id()));
1304 EXPECT_EQ(expected_remote_stream,
1305 report->Get(expected_remote_stream.id())->cast_to<
1306 RTCMediaStreamStats>());
1307
1308 RTCMediaStreamTrackStats expected_local_audio_track(
1309 "RTCMediaStreamTrack_LocalAudioTrackID", report->timestamp_us());
1310 expected_local_audio_track.track_identifier = local_audio_track->id();
1311 expected_local_audio_track.remote_source = false;
1312 expected_local_audio_track.ended = true;
1313 expected_local_audio_track.detached = false;
1314 expected_local_audio_track.audio_level = 1.0;
1315 expected_local_audio_track.echo_return_loss = 42.0;
1316 expected_local_audio_track.echo_return_loss_enhancement = 52.0;
1317 EXPECT_TRUE(report->Get(expected_local_audio_track.id()));
1318 EXPECT_EQ(expected_local_audio_track,
1319 report->Get(expected_local_audio_track.id())->cast_to<
1320 RTCMediaStreamTrackStats>());
1321
1322 RTCMediaStreamTrackStats expected_remote_audio_track(
1323 "RTCMediaStreamTrack_RemoteAudioTrackID", report->timestamp_us());
1324 expected_remote_audio_track.track_identifier = remote_audio_track->id();
1325 expected_remote_audio_track.remote_source = true;
1326 expected_remote_audio_track.ended = false;
1327 expected_remote_audio_track.detached = false;
1328 expected_remote_audio_track.audio_level = 0.0;
1329 expected_remote_audio_track.echo_return_loss = 13.0;
1330 expected_remote_audio_track.echo_return_loss_enhancement = 37.0;
1331 EXPECT_TRUE(report->Get(expected_remote_audio_track.id()));
1332 EXPECT_EQ(expected_remote_audio_track,
1333 report->Get(expected_remote_audio_track.id())->cast_to<
1334 RTCMediaStreamTrackStats>());
1335}
1336
1337TEST_F(RTCStatsCollectorTest,
1338 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
1339 rtc::scoped_refptr<StreamCollection> local_streams =
1340 StreamCollection::Create();
1341 rtc::scoped_refptr<StreamCollection> remote_streams =
1342 StreamCollection::Create();
1343 EXPECT_CALL(test_->pc(), local_streams())
1344 .WillRepeatedly(Return(local_streams));
1345 EXPECT_CALL(test_->pc(), remote_streams())
1346 .WillRepeatedly(Return(remote_streams));
1347
1348 rtc::scoped_refptr<MediaStream> local_stream =
1349 MediaStream::Create("LocalStreamLabel");
1350 local_streams->AddStream(local_stream);
1351 rtc::scoped_refptr<MediaStream> remote_stream =
1352 MediaStream::Create("RemoteStreamLabel");
1353 remote_streams->AddStream(remote_stream);
1354
1355 // Local video track
1356 VideoTrackSourceInterface::Stats local_video_track_source_stats;
1357 local_video_track_source_stats.input_width = 1234;
1358 local_video_track_source_stats.input_height = 4321;
1359 rtc::scoped_refptr<FakeVideoTrackSourceForStats> local_video_track_source =
1360 new FakeVideoTrackSourceForStats(local_video_track_source_stats);
1361 rtc::scoped_refptr<FakeVideoTrackForStats> local_video_track =
1362 FakeVideoTrackForStats::Create(
1363 "LocalVideoTrackID",
1364 MediaStreamTrackInterface::TrackState::kLive,
1365 local_video_track_source);
1366 local_stream->AddTrack(local_video_track);
1367
1368 // Remote video track
1369 VideoTrackSourceInterface::Stats remote_video_track_source_stats;
1370 remote_video_track_source_stats.input_width = 1234;
1371 remote_video_track_source_stats.input_height = 4321;
1372 rtc::scoped_refptr<FakeVideoTrackSourceForStats> remote_video_track_source =
1373 new FakeVideoTrackSourceForStats(remote_video_track_source_stats);
1374 rtc::scoped_refptr<FakeVideoTrackForStats> remote_video_track =
1375 FakeVideoTrackForStats::Create(
1376 "RemoteVideoTrackID",
1377 MediaStreamTrackInterface::TrackState::kEnded,
1378 remote_video_track_source);
1379 remote_stream->AddTrack(remote_video_track);
1380
1381 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1382
1383 RTCMediaStreamStats expected_local_stream(
1384 "RTCMediaStream_LocalStreamLabel", report->timestamp_us());
1385 expected_local_stream.stream_identifier = local_stream->label();
1386 expected_local_stream.track_ids = std::vector<std::string>();
1387 expected_local_stream.track_ids->push_back(
1388 "RTCMediaStreamTrack_LocalVideoTrackID");
1389 EXPECT_TRUE(report->Get(expected_local_stream.id()));
1390 EXPECT_EQ(expected_local_stream,
1391 report->Get(expected_local_stream.id())->cast_to<
1392 RTCMediaStreamStats>());
1393
1394 RTCMediaStreamStats expected_remote_stream(
1395 "RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
1396 expected_remote_stream.stream_identifier = remote_stream->label();
1397 expected_remote_stream.track_ids = std::vector<std::string>();
1398 expected_remote_stream.track_ids->push_back(
1399 "RTCMediaStreamTrack_RemoteVideoTrackID");
1400 EXPECT_TRUE(report->Get(expected_remote_stream.id()));
1401 EXPECT_EQ(expected_remote_stream,
1402 report->Get(expected_remote_stream.id())->cast_to<
1403 RTCMediaStreamStats>());
1404
1405 RTCMediaStreamTrackStats expected_local_video_track(
1406 "RTCMediaStreamTrack_LocalVideoTrackID", report->timestamp_us());
1407 expected_local_video_track.track_identifier = local_video_track->id();
1408 expected_local_video_track.remote_source = false;
1409 expected_local_video_track.ended = false;
1410 expected_local_video_track.detached = false;
1411 expected_local_video_track.frame_width = 1234;
1412 expected_local_video_track.frame_height = 4321;
1413 EXPECT_TRUE(report->Get(expected_local_video_track.id()));
1414 EXPECT_EQ(expected_local_video_track,
1415 report->Get(expected_local_video_track.id())->cast_to<
1416 RTCMediaStreamTrackStats>());
1417
1418 RTCMediaStreamTrackStats expected_remote_video_track(
1419 "RTCMediaStreamTrack_RemoteVideoTrackID", report->timestamp_us());
1420 expected_remote_video_track.track_identifier = remote_video_track->id();
1421 expected_remote_video_track.remote_source = true;
1422 expected_remote_video_track.ended = true;
1423 expected_remote_video_track.detached = false;
1424 expected_remote_video_track.frame_width = 1234;
1425 expected_remote_video_track.frame_height = 4321;
1426 EXPECT_TRUE(report->Get(expected_remote_video_track.id()));
1427 EXPECT_EQ(expected_remote_video_track,
1428 report->Get(expected_remote_video_track.id())->cast_to<
1429 RTCMediaStreamTrackStats>());
1430}
1431
hboseeafe942016-11-01 03:00:17 -07001432TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
1433 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
1434 cricket::VoiceChannel voice_channel(
1435 test_->worker_thread(), test_->network_thread(), test_->media_engine(),
1436 voice_media_channel, nullptr, "VoiceContentName", false);
1437
1438 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001439
hboseeafe942016-11-01 03:00:17 -07001440 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1441 voice_media_info.receivers[0].local_stats.push_back(
1442 cricket::SsrcReceiverInfo());
1443 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
1444 voice_media_info.receivers[0].packets_rcvd = 2;
1445 voice_media_info.receivers[0].bytes_rcvd = 3;
hbos0adb8282016-11-23 02:32:06 -08001446 voice_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42);
hboseeafe942016-11-01 03:00:17 -07001447 voice_media_info.receivers[0].jitter_ms = 4500;
1448 voice_media_info.receivers[0].fraction_lost = 5.5f;
hbos0adb8282016-11-23 02:32:06 -08001449
1450 RtpCodecParameters codec_parameters;
1451 codec_parameters.payload_type = 42;
1452 codec_parameters.mime_type = "dummy";
1453 codec_parameters.clock_rate = 0;
1454 voice_media_info.receive_codecs.insert(
1455 std::make_pair(codec_parameters.payload_type, codec_parameters));
1456
hboseeafe942016-11-01 03:00:17 -07001457 EXPECT_CALL(*voice_media_channel, GetStats(_))
1458 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
1459
1460 SessionStats session_stats;
1461 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
1462 session_stats.transport_stats["TransportName"].transport_name =
1463 "TransportName";
1464
1465 // Make sure the associated |RTCTransportStats| is created.
1466 cricket::TransportChannelStats channel_stats;
1467 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1468 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1469 channel_stats);
1470
1471 EXPECT_CALL(test_->session(), GetTransportStats(_))
1472 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1473 EXPECT_CALL(test_->session(), voice_channel())
1474 .WillRepeatedly(Return(&voice_channel));
1475
1476 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1477
1478 RTCInboundRTPStreamStats expected_audio(
1479 "RTCInboundRTPAudioStream_1", report->timestamp_us());
1480 expected_audio.ssrc = "1";
1481 expected_audio.is_remote = false;
1482 expected_audio.media_type = "audio";
1483 expected_audio.transport_id = "RTCTransport_TransportName_" +
1484 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0adb8282016-11-23 02:32:06 -08001485 expected_audio.codec_id = "RTCCodec_InboundAudio_42";
hboseeafe942016-11-01 03:00:17 -07001486 expected_audio.packets_received = 2;
1487 expected_audio.bytes_received = 3;
1488 expected_audio.jitter = 4.5;
1489 expected_audio.fraction_lost = 5.5;
1490
1491 ASSERT(report->Get(expected_audio.id()));
1492 const RTCInboundRTPStreamStats& audio = report->Get(
1493 expected_audio.id())->cast_to<RTCInboundRTPStreamStats>();
1494 EXPECT_EQ(audio, expected_audio);
1495
1496 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
hbos0adb8282016-11-23 02:32:06 -08001497 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hboseeafe942016-11-01 03:00:17 -07001498}
1499
1500TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
1501 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
1502 cricket::VideoChannel video_channel(
1503 test_->worker_thread(), test_->network_thread(), video_media_channel,
1504 nullptr, "VideoContentName", false);
1505
1506 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001507
hboseeafe942016-11-01 03:00:17 -07001508 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1509 video_media_info.receivers[0].local_stats.push_back(
1510 cricket::SsrcReceiverInfo());
1511 video_media_info.receivers[0].local_stats[0].ssrc = 1;
1512 video_media_info.receivers[0].packets_rcvd = 2;
1513 video_media_info.receivers[0].bytes_rcvd = 3;
1514 video_media_info.receivers[0].fraction_lost = 4.5f;
hbos0adb8282016-11-23 02:32:06 -08001515 video_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42);
hbos820f5782016-11-22 03:16:50 -08001516 video_media_info.receivers[0].firs_sent = 5;
1517 video_media_info.receivers[0].plis_sent = 6;
1518 video_media_info.receivers[0].nacks_sent = 7;
hbos0adb8282016-11-23 02:32:06 -08001519
1520 RtpCodecParameters codec_parameters;
1521 codec_parameters.payload_type = 42;
1522 codec_parameters.mime_type = "dummy";
1523 codec_parameters.clock_rate = 0;
1524 video_media_info.receive_codecs.insert(
1525 std::make_pair(codec_parameters.payload_type, codec_parameters));
1526
hboseeafe942016-11-01 03:00:17 -07001527 EXPECT_CALL(*video_media_channel, GetStats(_))
1528 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
1529
1530 SessionStats session_stats;
1531 session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
1532 session_stats.transport_stats["TransportName"].transport_name =
1533 "TransportName";
1534
1535 // Make sure the associated |RTCTransportStats| is created.
1536 cricket::TransportChannelStats channel_stats;
1537 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1538 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1539 channel_stats);
1540
1541 EXPECT_CALL(test_->session(), GetTransportStats(_))
1542 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1543 EXPECT_CALL(test_->session(), video_channel())
1544 .WillRepeatedly(Return(&video_channel));
1545
1546 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1547
hbos820f5782016-11-22 03:16:50 -08001548 RTCInboundRTPStreamStats expected_video(
hboseeafe942016-11-01 03:00:17 -07001549 "RTCInboundRTPVideoStream_1", report->timestamp_us());
hbos820f5782016-11-22 03:16:50 -08001550 expected_video.ssrc = "1";
1551 expected_video.is_remote = false;
1552 expected_video.media_type = "video";
1553 expected_video.transport_id = "RTCTransport_TransportName_" +
hboseeafe942016-11-01 03:00:17 -07001554 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0adb8282016-11-23 02:32:06 -08001555 expected_video.codec_id = "RTCCodec_InboundVideo_42";
hbos820f5782016-11-22 03:16:50 -08001556 expected_video.fir_count = 5;
1557 expected_video.pli_count = 6;
1558 expected_video.nack_count = 7;
1559 expected_video.packets_received = 2;
1560 expected_video.bytes_received = 3;
1561 expected_video.fraction_lost = 4.5;
hboseeafe942016-11-01 03:00:17 -07001562
hbos820f5782016-11-22 03:16:50 -08001563 ASSERT(report->Get(expected_video.id()));
1564 const RTCInboundRTPStreamStats& video = report->Get(
1565 expected_video.id())->cast_to<RTCInboundRTPStreamStats>();
1566 EXPECT_EQ(video, expected_video);
hboseeafe942016-11-01 03:00:17 -07001567
hbos820f5782016-11-22 03:16:50 -08001568 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbos0adb8282016-11-23 02:32:06 -08001569 EXPECT_TRUE(report->Get(*video.codec_id));
hboseeafe942016-11-01 03:00:17 -07001570}
1571
hbos6ded1902016-11-01 01:50:46 -07001572TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
1573 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
1574 cricket::VoiceChannel voice_channel(
1575 test_->worker_thread(), test_->network_thread(), test_->media_engine(),
1576 voice_media_channel, nullptr, "VoiceContentName", false);
1577
1578 cricket::VoiceMediaInfo voice_media_info;
hbos0adb8282016-11-23 02:32:06 -08001579
hbos6ded1902016-11-01 01:50:46 -07001580 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1581 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1582 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1583 voice_media_info.senders[0].packets_sent = 2;
1584 voice_media_info.senders[0].bytes_sent = 3;
hboseeafe942016-11-01 03:00:17 -07001585 voice_media_info.senders[0].rtt_ms = 4500;
hbos0adb8282016-11-23 02:32:06 -08001586 voice_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42);
1587
1588 RtpCodecParameters codec_parameters;
1589 codec_parameters.payload_type = 42;
1590 codec_parameters.mime_type = "dummy";
1591 codec_parameters.clock_rate = 0;
1592 voice_media_info.send_codecs.insert(
1593 std::make_pair(codec_parameters.payload_type, codec_parameters));
1594
hbos6ded1902016-11-01 01:50:46 -07001595 EXPECT_CALL(*voice_media_channel, GetStats(_))
1596 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
1597
1598 SessionStats session_stats;
1599 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
1600 session_stats.transport_stats["TransportName"].transport_name =
1601 "TransportName";
1602
1603 // Make sure the associated |RTCTransportStats| is created.
1604 cricket::TransportChannelStats channel_stats;
1605 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
hbos6ded1902016-11-01 01:50:46 -07001606 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1607 channel_stats);
1608
1609 EXPECT_CALL(test_->session(), GetTransportStats(_))
1610 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1611 EXPECT_CALL(test_->session(), voice_channel())
1612 .WillRepeatedly(Return(&voice_channel));
1613
1614 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1615
1616 RTCOutboundRTPStreamStats expected_audio(
1617 "RTCOutboundRTPAudioStream_1", report->timestamp_us());
1618 expected_audio.ssrc = "1";
1619 expected_audio.is_remote = false;
1620 expected_audio.media_type = "audio";
1621 expected_audio.transport_id = "RTCTransport_TransportName_" +
1622 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0adb8282016-11-23 02:32:06 -08001623 expected_audio.codec_id = "RTCCodec_OutboundAudio_42";
hbos6ded1902016-11-01 01:50:46 -07001624 expected_audio.packets_sent = 2;
1625 expected_audio.bytes_sent = 3;
1626 expected_audio.round_trip_time = 4.5;
1627
1628 ASSERT(report->Get(expected_audio.id()));
1629 const RTCOutboundRTPStreamStats& audio = report->Get(
1630 expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>();
1631 EXPECT_EQ(audio, expected_audio);
1632
1633 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
hbos0adb8282016-11-23 02:32:06 -08001634 EXPECT_TRUE(report->Get(*expected_audio.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001635}
1636
1637TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
1638 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
1639 cricket::VideoChannel video_channel(
1640 test_->worker_thread(), test_->network_thread(), video_media_channel,
1641 nullptr, "VideoContentName", false);
1642
1643 cricket::VideoMediaInfo video_media_info;
hbos0adb8282016-11-23 02:32:06 -08001644
hbos6ded1902016-11-01 01:50:46 -07001645 video_media_info.senders.push_back(cricket::VideoSenderInfo());
1646 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1647 video_media_info.senders[0].local_stats[0].ssrc = 1;
1648 video_media_info.senders[0].firs_rcvd = 2;
1649 video_media_info.senders[0].plis_rcvd = 3;
1650 video_media_info.senders[0].nacks_rcvd = 4;
1651 video_media_info.senders[0].packets_sent = 5;
1652 video_media_info.senders[0].bytes_sent = 6;
hboseeafe942016-11-01 03:00:17 -07001653 video_media_info.senders[0].rtt_ms = 7500;
hbos0adb8282016-11-23 02:32:06 -08001654 video_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42);
1655
1656 RtpCodecParameters codec_parameters;
1657 codec_parameters.payload_type = 42;
1658 codec_parameters.mime_type = "dummy";
1659 codec_parameters.clock_rate = 0;
1660 video_media_info.send_codecs.insert(
1661 std::make_pair(codec_parameters.payload_type, codec_parameters));
1662
hbos6ded1902016-11-01 01:50:46 -07001663 EXPECT_CALL(*video_media_channel, GetStats(_))
1664 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
1665
1666 SessionStats session_stats;
1667 session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
1668 session_stats.transport_stats["TransportName"].transport_name =
1669 "TransportName";
1670
1671 // Make sure the associated |RTCTransportStats| is created.
1672 cricket::TransportChannelStats channel_stats;
1673 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
hbos6ded1902016-11-01 01:50:46 -07001674 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1675 channel_stats);
1676
1677 EXPECT_CALL(test_->session(), GetTransportStats(_))
1678 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1679 EXPECT_CALL(test_->session(), video_channel())
1680 .WillRepeatedly(Return(&video_channel));
1681
1682 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1683
1684 RTCOutboundRTPStreamStats expected_video(
1685 "RTCOutboundRTPVideoStream_1", report->timestamp_us());
1686 expected_video.ssrc = "1";
1687 expected_video.is_remote = false;
1688 expected_video.media_type = "video";
1689 expected_video.transport_id = "RTCTransport_TransportName_" +
1690 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
hbos0adb8282016-11-23 02:32:06 -08001691 expected_video.codec_id = "RTCCodec_OutboundVideo_42";
hbos6ded1902016-11-01 01:50:46 -07001692 expected_video.fir_count = 2;
1693 expected_video.pli_count = 3;
1694 expected_video.nack_count = 4;
1695 expected_video.packets_sent = 5;
1696 expected_video.bytes_sent = 6;
1697 expected_video.round_trip_time = 7.5;
1698
1699 ASSERT(report->Get(expected_video.id()));
1700 const RTCOutboundRTPStreamStats& video = report->Get(
1701 expected_video.id())->cast_to<RTCOutboundRTPStreamStats>();
1702 EXPECT_EQ(video, expected_video);
1703
1704 EXPECT_TRUE(report->Get(*expected_video.transport_id));
hbos0adb8282016-11-23 02:32:06 -08001705 EXPECT_TRUE(report->Get(*expected_video.codec_id));
hbos6ded1902016-11-01 01:50:46 -07001706}
1707
hbos2fa7c672016-10-24 04:00:05 -07001708TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
1709 std::unique_ptr<cricket::Candidate> rtp_local_candidate = CreateFakeCandidate(
1710 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1711 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
1712 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1713 cricket::LOCAL_PORT_TYPE, 42);
1714 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
1715 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1716 cricket::LOCAL_PORT_TYPE, 42);
1717 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
1718 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1719 cricket::LOCAL_PORT_TYPE, 42);
1720
1721 SessionStats session_stats;
1722 session_stats.transport_stats["transport"].transport_name = "transport";
1723
1724 cricket::ConnectionInfo rtp_connection_info;
1725 rtp_connection_info.best_connection = false;
1726 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
1727 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
1728 rtp_connection_info.sent_total_bytes = 42;
1729 rtp_connection_info.recv_total_bytes = 1337;
1730 cricket::TransportChannelStats rtp_transport_channel_stats;
1731 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1732 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
1733 session_stats.transport_stats["transport"].channel_stats.push_back(
1734 rtp_transport_channel_stats);
1735
1736
1737 // Mock the session to return the desired candidates.
1738 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1739 [this, &session_stats](SessionStats* stats) {
1740 *stats = session_stats;
1741 return true;
1742 }));
1743
1744 // Get stats without RTCP, an active connection or certificates.
1745 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1746 ExpectReportContainsTransportStats(
1747 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1748
1749 cricket::ConnectionInfo rtcp_connection_info;
1750 rtcp_connection_info.best_connection = false;
1751 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
1752 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
1753 rtcp_connection_info.sent_total_bytes = 1337;
1754 rtcp_connection_info.recv_total_bytes = 42;
1755 cricket::TransportChannelStats rtcp_transport_channel_stats;
1756 rtcp_transport_channel_stats.component =
1757 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
1758 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
1759 session_stats.transport_stats["transport"].channel_stats.push_back(
1760 rtcp_transport_channel_stats);
1761
1762 collector_->ClearCachedStatsReport();
1763 // Get stats with RTCP and without an active connection or certificates.
1764 report = GetStatsReport();
1765 ExpectReportContainsTransportStats(
1766 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1767
1768 // Get stats with an active connection.
1769 rtcp_connection_info.best_connection = true;
1770
1771 collector_->ClearCachedStatsReport();
1772 report = GetStatsReport();
1773 ExpectReportContainsTransportStats(
1774 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1775
1776 // Get stats with certificates.
1777 std::unique_ptr<CertificateInfo> local_certinfo =
1778 CreateFakeCertificateAndInfoFromDers(
1779 std::vector<std::string>({ "(local) local", "(local) chain" }));
1780 std::unique_ptr<CertificateInfo> remote_certinfo =
1781 CreateFakeCertificateAndInfoFromDers(
1782 std::vector<std::string>({ "(remote) local", "(remote) chain" }));
1783 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
1784 Invoke([this, &local_certinfo](const std::string& transport_name,
1785 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
1786 if (transport_name == "transport") {
1787 *certificate = local_certinfo->certificate;
1788 return true;
1789 }
1790 return false;
1791 }));
1792 EXPECT_CALL(test_->session(),
1793 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
1794 [this, &remote_certinfo](const std::string& transport_name) {
1795 if (transport_name == "transport")
1796 return remote_certinfo->certificate->ssl_certificate().GetReference();
1797 return static_cast<rtc::SSLCertificate*>(nullptr);
1798 }));
1799
1800 collector_->ClearCachedStatsReport();
1801 report = GetStatsReport();
1802 ExpectReportContainsTransportStats(
1803 report, session_stats.transport_stats["transport"],
1804 local_certinfo.get(), remote_certinfo.get());
1805}
1806
hbosc82f2e12016-09-05 01:36:50 -07001807class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
1808 public:
1809 RTCStatsCollectorTestWithFakeCollector()
1810 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
1811 collector_(FakeRTCStatsCollector::Create(
1812 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
1813 }
1814
1815 protected:
1816 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
1817 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
1818};
1819
1820TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
1821 collector_->VerifyThreadUsageAndResultsMerging();
1822}
1823
1824} // namespace
1825
hbosd565b732016-08-30 14:04:35 -07001826} // namespace webrtc