blob: 020a759a68ec5a470a66ede1a91555dc4b5f1466 [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>
14#include <string>
15#include <vector>
16
17#include "webrtc/api/jsepsessiondescription.h"
hbos74e1a4f2016-09-15 23:33:01 -070018#include "webrtc/api/stats/rtcstats_objects.h"
19#include "webrtc/api/stats/rtcstatsreport.h"
hbosd565b732016-08-30 14:04:35 -070020#include "webrtc/api/test/mock_datachannel.h"
21#include "webrtc/api/test/mock_peerconnection.h"
22#include "webrtc/api/test/mock_webrtcsession.h"
23#include "webrtc/base/checks.h"
hbos0e6758d2016-08-31 07:57:36 -070024#include "webrtc/base/fakeclock.h"
hbos6ab97ce2016-10-03 14:16:56 -070025#include "webrtc/base/fakesslidentity.h"
hbosd565b732016-08-30 14:04:35 -070026#include "webrtc/base/gunit.h"
27#include "webrtc/base/logging.h"
hbosc82f2e12016-09-05 01:36:50 -070028#include "webrtc/base/thread_checker.h"
hbos0e6758d2016-08-31 07:57:36 -070029#include "webrtc/base/timedelta.h"
30#include "webrtc/base/timeutils.h"
hbosd565b732016-08-30 14:04:35 -070031#include "webrtc/media/base/fakemediaengine.h"
32
hbos6ab97ce2016-10-03 14:16:56 -070033using testing::_;
34using testing::Invoke;
hbosd565b732016-08-30 14:04:35 -070035using testing::Return;
36using testing::ReturnRef;
37
38namespace webrtc {
39
hbosc82f2e12016-09-05 01:36:50 -070040namespace {
41
42const int64_t kGetStatsReportTimeoutMs = 1000;
43
hbos6ab97ce2016-10-03 14:16:56 -070044struct CertificateInfo {
45 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
46 std::vector<std::string> ders;
47 std::vector<std::string> pems;
48 std::vector<std::string> fingerprints;
49};
50
51std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
52 const std::vector<std::string>& ders) {
53 RTC_CHECK(!ders.empty());
54 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
55 info->ders = ders;
56 for (const std::string& der : ders) {
57 info->pems.push_back(rtc::SSLIdentity::DerToPem(
58 "CERTIFICATE",
59 reinterpret_cast<const unsigned char*>(der.c_str()),
60 der.length()));
61 }
62 info->certificate =
63 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
64 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
65 // Strip header/footer and newline characters of PEM strings.
66 for (size_t i = 0; i < info->pems.size(); ++i) {
67 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
68 "", 0, &info->pems[i]);
69 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
70 "", 0, &info->pems[i]);
71 rtc::replace_substrs("\n", 1,
72 "", 0, &info->pems[i]);
73 }
74 // Fingerprint of leaf certificate.
75 std::unique_ptr<rtc::SSLFingerprint> fp(
76 rtc::SSLFingerprint::Create("sha-1",
77 &info->certificate->ssl_certificate()));
78 EXPECT_TRUE(fp);
79 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
80 // Fingerprints of the rest of the chain.
81 std::unique_ptr<rtc::SSLCertChain> chain =
82 info->certificate->ssl_certificate().GetChain();
83 if (chain) {
84 for (size_t i = 0; i < chain->GetSize(); i++) {
85 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
86 EXPECT_TRUE(fp);
87 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
88 }
89 }
90 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
91 return info;
92}
93
hbosc82f2e12016-09-05 01:36:50 -070094class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
hbosd565b732016-08-30 14:04:35 -070095 public:
hbosc82f2e12016-09-05 01:36:50 -070096 RTCStatsCollectorTestHelper()
hbosd565b732016-08-30 14:04:35 -070097 : worker_thread_(rtc::Thread::Current()),
98 network_thread_(rtc::Thread::Current()),
99 channel_manager_(new cricket::ChannelManager(
100 new cricket::FakeMediaEngine(),
101 worker_thread_,
102 network_thread_)),
103 media_controller_(
104 MediaControllerInterface::Create(cricket::MediaConfig(),
105 worker_thread_,
106 channel_manager_.get())),
107 session_(media_controller_.get()),
108 pc_() {
hbos6ab97ce2016-10-03 14:16:56 -0700109 // Default return values for mocks.
hbosd565b732016-08-30 14:04:35 -0700110 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
111 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
112 ReturnRef(data_channels_));
hbos6ab97ce2016-10-03 14:16:56 -0700113 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
hbosd565b732016-08-30 14:04:35 -0700114 }
115
hbosfdafab82016-09-14 06:02:13 -0700116 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; }
hbosd565b732016-08-30 14:04:35 -0700117 MockWebRtcSession& session() { return session_; }
118 MockPeerConnection& pc() { return pc_; }
119 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() {
120 return data_channels_;
121 }
122
123 // SetSessionDescriptionObserver overrides.
124 void OnSuccess() override {}
125 void OnFailure(const std::string& error) override {
126 RTC_NOTREACHED() << error;
127 }
128
129 private:
hbosfdafab82016-09-14 06:02:13 -0700130 rtc::ScopedFakeClock fake_clock_;
hbosd565b732016-08-30 14:04:35 -0700131 rtc::Thread* const worker_thread_;
132 rtc::Thread* const network_thread_;
133 std::unique_ptr<cricket::ChannelManager> channel_manager_;
134 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
135 MockWebRtcSession session_;
136 MockPeerConnection pc_;
137
138 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
139};
140
hbosc82f2e12016-09-05 01:36:50 -0700141class RTCTestStats : public RTCStats {
hbosd565b732016-08-30 14:04:35 -0700142 public:
hbosc82f2e12016-09-05 01:36:50 -0700143 RTCTestStats(const std::string& id, int64_t timestamp_us)
144 : RTCStats(id, timestamp_us),
145 dummy_stat("dummyStat") {}
146
147 WEBRTC_RTCSTATS_IMPL(RTCStats, RTCTestStats,
148 &dummy_stat);
149
150 RTCStatsMember<int32_t> dummy_stat;
151};
152
153const char RTCTestStats::kType[] = "test-stats";
154
155// Overrides the stats collection to verify thread usage and that the resulting
156// partial reports are merged.
157class FakeRTCStatsCollector : public RTCStatsCollector,
158 public RTCStatsCollectorCallback {
159 public:
160 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
161 PeerConnection* pc,
162 int64_t cache_lifetime_us) {
163 return rtc::scoped_refptr<FakeRTCStatsCollector>(
164 new rtc::RefCountedObject<FakeRTCStatsCollector>(
165 pc, cache_lifetime_us));
166 }
167
168 // RTCStatsCollectorCallback implementation.
169 void OnStatsDelivered(
170 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
171 EXPECT_TRUE(signaling_thread_->IsCurrent());
172 rtc::CritScope cs(&lock_);
173 delivered_report_ = report;
174 }
175
176 void VerifyThreadUsageAndResultsMerging() {
177 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
178 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
179 }
180
181 bool HasVerifiedResults() {
182 EXPECT_TRUE(signaling_thread_->IsCurrent());
183 rtc::CritScope cs(&lock_);
184 if (!delivered_report_)
185 return false;
186 EXPECT_EQ(produced_on_signaling_thread_, 1);
187 EXPECT_EQ(produced_on_worker_thread_, 1);
188 EXPECT_EQ(produced_on_network_thread_, 1);
189
190 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
191 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
192 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
193
194 produced_on_signaling_thread_ = 0;
195 produced_on_worker_thread_ = 0;
196 produced_on_network_thread_ = 0;
197 delivered_report_ = nullptr;
198 return true;
hbosd565b732016-08-30 14:04:35 -0700199 }
200
201 protected:
hbosc82f2e12016-09-05 01:36:50 -0700202 FakeRTCStatsCollector(
203 PeerConnection* pc,
204 int64_t cache_lifetime)
205 : RTCStatsCollector(pc, cache_lifetime),
206 signaling_thread_(pc->session()->signaling_thread()),
207 worker_thread_(pc->session()->worker_thread()),
208 network_thread_(pc->session()->network_thread()) {
209 }
210
211 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
212 EXPECT_TRUE(signaling_thread_->IsCurrent());
213 {
214 rtc::CritScope cs(&lock_);
215 EXPECT_FALSE(delivered_report_);
216 ++produced_on_signaling_thread_;
217 }
218
219 rtc::scoped_refptr<RTCStatsReport> signaling_report =
220 RTCStatsReport::Create();
221 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
222 new RTCTestStats("SignalingThreadStats", timestamp_us)));
223 AddPartialResults(signaling_report);
224 }
225 void ProducePartialResultsOnWorkerThread(int64_t timestamp_us) override {
226 EXPECT_TRUE(worker_thread_->IsCurrent());
227 {
228 rtc::CritScope cs(&lock_);
229 EXPECT_FALSE(delivered_report_);
230 ++produced_on_worker_thread_;
231 }
232
233 rtc::scoped_refptr<RTCStatsReport> worker_report = RTCStatsReport::Create();
234 worker_report->AddStats(std::unique_ptr<const RTCStats>(
235 new RTCTestStats("WorkerThreadStats", timestamp_us)));
236 AddPartialResults(worker_report);
237 }
238 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
239 EXPECT_TRUE(network_thread_->IsCurrent());
240 {
241 rtc::CritScope cs(&lock_);
242 EXPECT_FALSE(delivered_report_);
243 ++produced_on_network_thread_;
244 }
245
246 rtc::scoped_refptr<RTCStatsReport> network_report =
247 RTCStatsReport::Create();
248 network_report->AddStats(std::unique_ptr<const RTCStats>(
249 new RTCTestStats("NetworkThreadStats", timestamp_us)));
250 AddPartialResults(network_report);
251 }
252
253 private:
254 rtc::Thread* const signaling_thread_;
255 rtc::Thread* const worker_thread_;
256 rtc::Thread* const network_thread_;
257
258 rtc::CriticalSection lock_;
259 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
260 int produced_on_signaling_thread_ = 0;
261 int produced_on_worker_thread_ = 0;
262 int produced_on_network_thread_ = 0;
hbosd565b732016-08-30 14:04:35 -0700263};
264
hbosc82f2e12016-09-05 01:36:50 -0700265class StatsCallback : public RTCStatsCollectorCallback {
266 public:
267 static rtc::scoped_refptr<StatsCallback> Create(
268 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
269 return rtc::scoped_refptr<StatsCallback>(
270 new rtc::RefCountedObject<StatsCallback>(report_ptr));
271 }
272
273 void OnStatsDelivered(
274 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
275 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
276 report_ = report;
277 if (report_ptr_)
278 *report_ptr_ = report_;
279 }
280
281 rtc::scoped_refptr<const RTCStatsReport> report() const {
282 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
283 return report_;
284 }
285
286 protected:
287 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
288 : report_ptr_(report_ptr) {}
289
290 private:
291 rtc::ThreadChecker thread_checker_;
292 rtc::scoped_refptr<const RTCStatsReport> report_;
293 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
294};
295
296class RTCStatsCollectorTest : public testing::Test {
297 public:
298 RTCStatsCollectorTest()
299 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
300 collector_(RTCStatsCollector::Create(
301 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
302 }
303
304 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
305 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
306 collector_->GetStatsReport(callback);
307 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
308 return callback->report();
309 }
310
hbos6ab97ce2016-10-03 14:16:56 -0700311 void ExpectReportContainsCertificateInfo(
312 const rtc::scoped_refptr<const RTCStatsReport>& report,
313 const CertificateInfo& cert_info) {
314 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
315 const RTCStats* stats = report->Get(
316 "RTCCertificate_" + cert_info.fingerprints[i]);
317 EXPECT_TRUE(stats);
318 const RTCCertificateStats& cert_stats =
319 stats->cast_to<const RTCCertificateStats>();
320 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
321 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
322 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
323 if (i + 1 < cert_info.fingerprints.size()) {
324 EXPECT_EQ(*cert_stats.issuer_certificate_id,
325 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
326 } else {
327 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
328 }
329 }
330 }
331
hbosc82f2e12016-09-05 01:36:50 -0700332 protected:
333 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
334 rtc::scoped_refptr<RTCStatsCollector> collector_;
335};
336
337TEST_F(RTCStatsCollectorTest, SingleCallback) {
338 rtc::scoped_refptr<const RTCStatsReport> result;
339 collector_->GetStatsReport(StatsCallback::Create(&result));
340 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
341}
342
343TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
344 rtc::scoped_refptr<const RTCStatsReport> a;
345 rtc::scoped_refptr<const RTCStatsReport> b;
346 rtc::scoped_refptr<const RTCStatsReport> c;
347 collector_->GetStatsReport(StatsCallback::Create(&a));
348 collector_->GetStatsReport(StatsCallback::Create(&b));
349 collector_->GetStatsReport(StatsCallback::Create(&c));
350 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
351 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
352 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
353 EXPECT_EQ(a.get(), b.get());
354 EXPECT_EQ(b.get(), c.get());
355}
356
357TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700358 // Caching should ensure |a| and |b| are the same report.
hbosc82f2e12016-09-05 01:36:50 -0700359 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
360 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700361 EXPECT_EQ(a.get(), b.get());
362 // Invalidate cache by clearing it.
hbosc82f2e12016-09-05 01:36:50 -0700363 collector_->ClearCachedStatsReport();
364 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700365 EXPECT_NE(b.get(), c.get());
366 // Invalidate cache by advancing time.
hbosfdafab82016-09-14 06:02:13 -0700367 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700368 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700369 EXPECT_TRUE(d);
370 EXPECT_NE(c.get(), d.get());
371}
372
hbosc82f2e12016-09-05 01:36:50 -0700373TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
hbosc82f2e12016-09-05 01:36:50 -0700374 rtc::scoped_refptr<const RTCStatsReport> a;
375 rtc::scoped_refptr<const RTCStatsReport> b;
376 rtc::scoped_refptr<const RTCStatsReport> c;
377 collector_->GetStatsReport(StatsCallback::Create(&a));
378 collector_->GetStatsReport(StatsCallback::Create(&b));
379 // Cache is invalidated after 50 ms.
hbosfdafab82016-09-14 06:02:13 -0700380 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700381 collector_->GetStatsReport(StatsCallback::Create(&c));
382 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
383 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
384 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
385 EXPECT_EQ(a.get(), b.get());
386 // The act of doing |AdvanceTime| processes all messages. If this was not the
387 // case we might not require |c| to be fresher than |b|.
388 EXPECT_NE(c.get(), b.get());
389}
390
hbos6ab97ce2016-10-03 14:16:56 -0700391TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
392 std::unique_ptr<CertificateInfo> local_certinfo =
393 CreateFakeCertificateAndInfoFromDers(
394 std::vector<std::string>({ "(local) single certificate" }));
395 std::unique_ptr<CertificateInfo> remote_certinfo =
396 CreateFakeCertificateAndInfoFromDers(
397 std::vector<std::string>({ "(remote) single certificate" }));
398
399 // Mock the session to return the local and remote certificates.
400 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
401 [this](SessionStats* stats) {
402 stats->transport_stats["transport"].transport_name = "transport";
403 return true;
404 }));
405 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
406 Invoke([this, &local_certinfo](const std::string& transport_name,
407 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
408 if (transport_name == "transport") {
409 *certificate = local_certinfo->certificate;
410 return true;
411 }
412 return false;
413 }));
414 EXPECT_CALL(test_->session(),
415 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
416 [this, &remote_certinfo](const std::string& transport_name) {
417 if (transport_name == "transport")
418 return remote_certinfo->certificate->ssl_certificate().GetReference();
419 return static_cast<rtc::SSLCertificate*>(nullptr);
420 }));
421
422 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
423 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
424 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
425}
426
427TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
428 std::unique_ptr<CertificateInfo> audio_local_certinfo =
429 CreateFakeCertificateAndInfoFromDers(
430 std::vector<std::string>({ "(local) audio" }));
431 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
432 audio_local_certinfo->ders);
433 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
434 CreateFakeCertificateAndInfoFromDers(
435 std::vector<std::string>({ "(remote) audio" }));
436 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
437 audio_remote_certinfo->ders);
438
439 std::unique_ptr<CertificateInfo> video_local_certinfo =
440 CreateFakeCertificateAndInfoFromDers(
441 std::vector<std::string>({ "(local) video" }));
442 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
443 video_local_certinfo->ders);
444 std::unique_ptr<CertificateInfo> video_remote_certinfo =
445 CreateFakeCertificateAndInfoFromDers(
446 std::vector<std::string>({ "(remote) video" }));
447 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
448 video_remote_certinfo->ders);
449
450 // Mock the session to return the local and remote certificates.
451 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
452 [this](SessionStats* stats) {
453 stats->transport_stats["audio"].transport_name = "audio";
454 stats->transport_stats["video"].transport_name = "video";
455 return true;
456 }));
457 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
458 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
459 const std::string& transport_name,
460 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
461 if (transport_name == "audio") {
462 *certificate = audio_local_certinfo->certificate;
463 return true;
464 }
465 if (transport_name == "video") {
466 *certificate = video_local_certinfo->certificate;
467 return true;
468 }
469 return false;
470 }));
471 EXPECT_CALL(test_->session(),
472 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
473 [this, &audio_remote_certinfo, &video_remote_certinfo](
474 const std::string& transport_name) {
475 if (transport_name == "audio") {
476 return audio_remote_certinfo->certificate->ssl_certificate()
477 .GetReference();
478 }
479 if (transport_name == "video") {
480 return video_remote_certinfo->certificate->ssl_certificate()
481 .GetReference();
482 }
483 return static_cast<rtc::SSLCertificate*>(nullptr);
484 }));
485
486 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
487 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
488 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
489 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
490 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
491}
492
493TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
494 std::vector<std::string> local_ders;
495 local_ders.push_back("(local) this");
496 local_ders.push_back("(local) is");
497 local_ders.push_back("(local) a");
498 local_ders.push_back("(local) chain");
499 std::unique_ptr<CertificateInfo> local_certinfo =
500 CreateFakeCertificateAndInfoFromDers(local_ders);
501 std::vector<std::string> remote_ders;
502 remote_ders.push_back("(remote) this");
503 remote_ders.push_back("(remote) is");
504 remote_ders.push_back("(remote) another");
505 remote_ders.push_back("(remote) chain");
506 std::unique_ptr<CertificateInfo> remote_certinfo =
507 CreateFakeCertificateAndInfoFromDers(remote_ders);
508
509 // Mock the session to return the local and remote certificates.
510 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
511 [this](SessionStats* stats) {
512 stats->transport_stats["transport"].transport_name = "transport";
513 return true;
514 }));
515 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
516 Invoke([this, &local_certinfo](const std::string& transport_name,
517 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
518 if (transport_name == "transport") {
519 *certificate = local_certinfo->certificate;
520 return true;
521 }
522 return false;
523 }));
524 EXPECT_CALL(test_->session(),
525 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
526 [this, &remote_certinfo](const std::string& transport_name) {
527 if (transport_name == "transport")
528 return remote_certinfo->certificate->ssl_certificate().GetReference();
529 return static_cast<rtc::SSLCertificate*>(nullptr);
530 }));
531
532 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
533 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
534 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
535}
536
hbosd565b732016-08-30 14:04:35 -0700537TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
nissecdf37a92016-09-13 23:41:47 -0700538 int64_t before = rtc::TimeUTCMicros();
hbosc82f2e12016-09-05 01:36:50 -0700539 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
nissecdf37a92016-09-13 23:41:47 -0700540 int64_t after = rtc::TimeUTCMicros();
hbosd565b732016-08-30 14:04:35 -0700541 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
542 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
543 const RTCStats* stats = report->Get("RTCPeerConnection");
544 EXPECT_TRUE(stats);
hbos0e6758d2016-08-31 07:57:36 -0700545 EXPECT_LE(before, stats->timestamp_us());
546 EXPECT_LE(stats->timestamp_us(), after);
hbosd565b732016-08-30 14:04:35 -0700547 {
548 // Expected stats with no data channels
549 const RTCPeerConnectionStats& pcstats =
550 stats->cast_to<RTCPeerConnectionStats>();
551 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0));
552 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0));
553 }
554
555 test_->data_channels().push_back(
556 new MockDataChannel(DataChannelInterface::kConnecting));
557 test_->data_channels().push_back(
558 new MockDataChannel(DataChannelInterface::kOpen));
559 test_->data_channels().push_back(
560 new MockDataChannel(DataChannelInterface::kClosing));
561 test_->data_channels().push_back(
562 new MockDataChannel(DataChannelInterface::kClosed));
563
hbosc82f2e12016-09-05 01:36:50 -0700564 collector_->ClearCachedStatsReport();
565 report = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700566 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
567 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
568 stats = report->Get("RTCPeerConnection");
569 EXPECT_TRUE(stats);
570 {
571 // Expected stats with the above four data channels
572 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data
573 // channels that have been opened and closed, not the numbers currently
574 // open/closed, we would expect opened >= closed and (opened - closed) to be
575 // the number currently open. crbug.com/636818.
576 const RTCPeerConnectionStats& pcstats =
577 stats->cast_to<RTCPeerConnectionStats>();
578 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1));
579 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3));
580 }
581}
582
hbosc82f2e12016-09-05 01:36:50 -0700583class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
584 public:
585 RTCStatsCollectorTestWithFakeCollector()
586 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
587 collector_(FakeRTCStatsCollector::Create(
588 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
589 }
590
591 protected:
592 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
593 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
594};
595
596TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
597 collector_->VerifyThreadUsageAndResultsMerging();
598}
599
600} // namespace
601
hbosd565b732016-08-30 14:04:35 -0700602} // namespace webrtc