blob: 0da772fb97d3767682f5493442da9b41b6fa61c3 [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"
hbosab9f6e42016-10-07 02:18:47 -070028#include "webrtc/base/socketaddress.h"
hbosc82f2e12016-09-05 01:36:50 -070029#include "webrtc/base/thread_checker.h"
hbos0e6758d2016-08-31 07:57:36 -070030#include "webrtc/base/timedelta.h"
31#include "webrtc/base/timeutils.h"
skvlad11a9cbf2016-10-07 11:53:05 -070032#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
hbosd565b732016-08-30 14:04:35 -070033#include "webrtc/media/base/fakemediaengine.h"
hbosab9f6e42016-10-07 02:18:47 -070034#include "webrtc/p2p/base/port.h"
hbosd565b732016-08-30 14:04:35 -070035
hbos6ab97ce2016-10-03 14:16:56 -070036using testing::_;
37using testing::Invoke;
hbosd565b732016-08-30 14:04:35 -070038using testing::Return;
39using testing::ReturnRef;
40
41namespace webrtc {
42
hbosc82f2e12016-09-05 01:36:50 -070043namespace {
44
45const int64_t kGetStatsReportTimeoutMs = 1000;
46
hbos6ab97ce2016-10-03 14:16:56 -070047struct CertificateInfo {
48 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
49 std::vector<std::string> ders;
50 std::vector<std::string> pems;
51 std::vector<std::string> fingerprints;
52};
53
54std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
55 const std::vector<std::string>& ders) {
56 RTC_CHECK(!ders.empty());
57 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
58 info->ders = ders;
59 for (const std::string& der : ders) {
60 info->pems.push_back(rtc::SSLIdentity::DerToPem(
61 "CERTIFICATE",
62 reinterpret_cast<const unsigned char*>(der.c_str()),
63 der.length()));
64 }
65 info->certificate =
66 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
67 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
68 // Strip header/footer and newline characters of PEM strings.
69 for (size_t i = 0; i < info->pems.size(); ++i) {
70 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
71 "", 0, &info->pems[i]);
72 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
73 "", 0, &info->pems[i]);
74 rtc::replace_substrs("\n", 1,
75 "", 0, &info->pems[i]);
76 }
77 // Fingerprint of leaf certificate.
78 std::unique_ptr<rtc::SSLFingerprint> fp(
79 rtc::SSLFingerprint::Create("sha-1",
80 &info->certificate->ssl_certificate()));
81 EXPECT_TRUE(fp);
82 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
83 // Fingerprints of the rest of the chain.
84 std::unique_ptr<rtc::SSLCertChain> chain =
85 info->certificate->ssl_certificate().GetChain();
86 if (chain) {
87 for (size_t i = 0; i < chain->GetSize(); i++) {
88 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
89 EXPECT_TRUE(fp);
90 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
91 }
92 }
93 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
94 return info;
95}
96
hbosab9f6e42016-10-07 02:18:47 -070097std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
98 const std::string& hostname,
99 int port,
100 const std::string& protocol,
101 const std::string& candidate_type,
102 uint32_t priority) {
103 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
104 candidate->set_address(rtc::SocketAddress(hostname, port));
105 candidate->set_protocol(protocol);
106 candidate->set_type(candidate_type);
107 candidate->set_priority(priority);
108 return candidate;
109}
110
hbosc82f2e12016-09-05 01:36:50 -0700111class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
hbosd565b732016-08-30 14:04:35 -0700112 public:
hbosc82f2e12016-09-05 01:36:50 -0700113 RTCStatsCollectorTestHelper()
hbosd565b732016-08-30 14:04:35 -0700114 : worker_thread_(rtc::Thread::Current()),
115 network_thread_(rtc::Thread::Current()),
skvlad11a9cbf2016-10-07 11:53:05 -0700116 channel_manager_(
117 new cricket::ChannelManager(new cricket::FakeMediaEngine(),
118 worker_thread_,
119 network_thread_)),
hbosd565b732016-08-30 14:04:35 -0700120 media_controller_(
121 MediaControllerInterface::Create(cricket::MediaConfig(),
122 worker_thread_,
skvlad11a9cbf2016-10-07 11:53:05 -0700123 channel_manager_.get(),
124 &event_log_)),
hbosd565b732016-08-30 14:04:35 -0700125 session_(media_controller_.get()),
126 pc_() {
hbos6ab97ce2016-10-03 14:16:56 -0700127 // Default return values for mocks.
hbosd565b732016-08-30 14:04:35 -0700128 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
129 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
130 ReturnRef(data_channels_));
hbos6ab97ce2016-10-03 14:16:56 -0700131 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
hbosab9f6e42016-10-07 02:18:47 -0700132 EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly(
133 Return(false));
134 EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_))
135 .WillRepeatedly(Return(nullptr));
hbosd565b732016-08-30 14:04:35 -0700136 }
137
hbosfdafab82016-09-14 06:02:13 -0700138 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; }
hbosd565b732016-08-30 14:04:35 -0700139 MockWebRtcSession& session() { return session_; }
140 MockPeerConnection& pc() { return pc_; }
141 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() {
142 return data_channels_;
143 }
144
145 // SetSessionDescriptionObserver overrides.
146 void OnSuccess() override {}
147 void OnFailure(const std::string& error) override {
148 RTC_NOTREACHED() << error;
149 }
150
151 private:
hbosfdafab82016-09-14 06:02:13 -0700152 rtc::ScopedFakeClock fake_clock_;
skvlad11a9cbf2016-10-07 11:53:05 -0700153 webrtc::RtcEventLogNullImpl event_log_;
hbosd565b732016-08-30 14:04:35 -0700154 rtc::Thread* const worker_thread_;
155 rtc::Thread* const network_thread_;
156 std::unique_ptr<cricket::ChannelManager> channel_manager_;
157 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
158 MockWebRtcSession session_;
159 MockPeerConnection pc_;
160
161 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
162};
163
hbosc82f2e12016-09-05 01:36:50 -0700164class RTCTestStats : public RTCStats {
hbosd565b732016-08-30 14:04:35 -0700165 public:
hbosfc5e0502016-10-06 02:06:10 -0700166 WEBRTC_RTCSTATS_DECL();
167
hbosc82f2e12016-09-05 01:36:50 -0700168 RTCTestStats(const std::string& id, int64_t timestamp_us)
169 : RTCStats(id, timestamp_us),
170 dummy_stat("dummyStat") {}
171
hbosc82f2e12016-09-05 01:36:50 -0700172 RTCStatsMember<int32_t> dummy_stat;
173};
174
hbosfc5e0502016-10-06 02:06:10 -0700175WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats",
176 &dummy_stat);
hbosc82f2e12016-09-05 01:36:50 -0700177
178// Overrides the stats collection to verify thread usage and that the resulting
179// partial reports are merged.
180class FakeRTCStatsCollector : public RTCStatsCollector,
181 public RTCStatsCollectorCallback {
182 public:
183 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
184 PeerConnection* pc,
185 int64_t cache_lifetime_us) {
186 return rtc::scoped_refptr<FakeRTCStatsCollector>(
187 new rtc::RefCountedObject<FakeRTCStatsCollector>(
188 pc, cache_lifetime_us));
189 }
190
191 // RTCStatsCollectorCallback implementation.
192 void OnStatsDelivered(
193 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
194 EXPECT_TRUE(signaling_thread_->IsCurrent());
195 rtc::CritScope cs(&lock_);
196 delivered_report_ = report;
197 }
198
199 void VerifyThreadUsageAndResultsMerging() {
200 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
201 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
202 }
203
204 bool HasVerifiedResults() {
205 EXPECT_TRUE(signaling_thread_->IsCurrent());
206 rtc::CritScope cs(&lock_);
207 if (!delivered_report_)
208 return false;
209 EXPECT_EQ(produced_on_signaling_thread_, 1);
210 EXPECT_EQ(produced_on_worker_thread_, 1);
211 EXPECT_EQ(produced_on_network_thread_, 1);
212
213 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
214 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
215 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
216
217 produced_on_signaling_thread_ = 0;
218 produced_on_worker_thread_ = 0;
219 produced_on_network_thread_ = 0;
220 delivered_report_ = nullptr;
221 return true;
hbosd565b732016-08-30 14:04:35 -0700222 }
223
224 protected:
hbosc82f2e12016-09-05 01:36:50 -0700225 FakeRTCStatsCollector(
226 PeerConnection* pc,
227 int64_t cache_lifetime)
228 : RTCStatsCollector(pc, cache_lifetime),
229 signaling_thread_(pc->session()->signaling_thread()),
230 worker_thread_(pc->session()->worker_thread()),
231 network_thread_(pc->session()->network_thread()) {
232 }
233
234 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
235 EXPECT_TRUE(signaling_thread_->IsCurrent());
236 {
237 rtc::CritScope cs(&lock_);
238 EXPECT_FALSE(delivered_report_);
239 ++produced_on_signaling_thread_;
240 }
241
242 rtc::scoped_refptr<RTCStatsReport> signaling_report =
243 RTCStatsReport::Create();
244 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
245 new RTCTestStats("SignalingThreadStats", timestamp_us)));
246 AddPartialResults(signaling_report);
247 }
248 void ProducePartialResultsOnWorkerThread(int64_t timestamp_us) override {
249 EXPECT_TRUE(worker_thread_->IsCurrent());
250 {
251 rtc::CritScope cs(&lock_);
252 EXPECT_FALSE(delivered_report_);
253 ++produced_on_worker_thread_;
254 }
255
256 rtc::scoped_refptr<RTCStatsReport> worker_report = RTCStatsReport::Create();
257 worker_report->AddStats(std::unique_ptr<const RTCStats>(
258 new RTCTestStats("WorkerThreadStats", timestamp_us)));
259 AddPartialResults(worker_report);
260 }
261 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
262 EXPECT_TRUE(network_thread_->IsCurrent());
263 {
264 rtc::CritScope cs(&lock_);
265 EXPECT_FALSE(delivered_report_);
266 ++produced_on_network_thread_;
267 }
268
269 rtc::scoped_refptr<RTCStatsReport> network_report =
270 RTCStatsReport::Create();
271 network_report->AddStats(std::unique_ptr<const RTCStats>(
272 new RTCTestStats("NetworkThreadStats", timestamp_us)));
273 AddPartialResults(network_report);
274 }
275
276 private:
277 rtc::Thread* const signaling_thread_;
278 rtc::Thread* const worker_thread_;
279 rtc::Thread* const network_thread_;
280
281 rtc::CriticalSection lock_;
282 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
283 int produced_on_signaling_thread_ = 0;
284 int produced_on_worker_thread_ = 0;
285 int produced_on_network_thread_ = 0;
hbosd565b732016-08-30 14:04:35 -0700286};
287
hbosc82f2e12016-09-05 01:36:50 -0700288class StatsCallback : public RTCStatsCollectorCallback {
289 public:
290 static rtc::scoped_refptr<StatsCallback> Create(
291 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
292 return rtc::scoped_refptr<StatsCallback>(
293 new rtc::RefCountedObject<StatsCallback>(report_ptr));
294 }
295
296 void OnStatsDelivered(
297 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
298 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
299 report_ = report;
300 if (report_ptr_)
301 *report_ptr_ = report_;
302 }
303
304 rtc::scoped_refptr<const RTCStatsReport> report() const {
305 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
306 return report_;
307 }
308
309 protected:
310 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
311 : report_ptr_(report_ptr) {}
312
313 private:
314 rtc::ThreadChecker thread_checker_;
315 rtc::scoped_refptr<const RTCStatsReport> report_;
316 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
317};
318
319class RTCStatsCollectorTest : public testing::Test {
320 public:
321 RTCStatsCollectorTest()
322 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
323 collector_(RTCStatsCollector::Create(
324 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
325 }
326
327 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
328 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
329 collector_->GetStatsReport(callback);
330 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
331 return callback->report();
332 }
333
hbosab9f6e42016-10-07 02:18:47 -0700334 void ExpectReportContainsCandidate(
335 const rtc::scoped_refptr<const RTCStatsReport>& report,
336 const cricket::Candidate& candidate,
337 bool is_local) {
338 const RTCStats* stats =
339 report->Get("RTCIceCandidate_" + candidate.id());
340 EXPECT_TRUE(stats);
341 const RTCIceCandidateStats* candidate_stats;
342 if (is_local)
343 candidate_stats = &stats->cast_to<RTCLocalIceCandidateStats>();
344 else
345 candidate_stats = &stats->cast_to<RTCRemoteIceCandidateStats>();
346 EXPECT_EQ(*candidate_stats->ip, candidate.address().ipaddr().ToString());
347 EXPECT_EQ(*candidate_stats->port,
348 static_cast<int32_t>(candidate.address().port()));
349 EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
350 EXPECT_EQ(*candidate_stats->candidate_type,
351 CandidateTypeToRTCIceCandidateType(candidate.type()));
352 EXPECT_EQ(*candidate_stats->priority,
353 static_cast<int32_t>(candidate.priority()));
354 // TODO(hbos): Define candidate_stats->url. crbug.com/632723
355 EXPECT_FALSE(candidate_stats->url.is_defined());
356 }
357
hbos6ab97ce2016-10-03 14:16:56 -0700358 void ExpectReportContainsCertificateInfo(
359 const rtc::scoped_refptr<const RTCStatsReport>& report,
360 const CertificateInfo& cert_info) {
361 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
362 const RTCStats* stats = report->Get(
363 "RTCCertificate_" + cert_info.fingerprints[i]);
364 EXPECT_TRUE(stats);
365 const RTCCertificateStats& cert_stats =
366 stats->cast_to<const RTCCertificateStats>();
367 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
368 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
369 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
370 if (i + 1 < cert_info.fingerprints.size()) {
371 EXPECT_EQ(*cert_stats.issuer_certificate_id,
372 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
373 } else {
374 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
375 }
376 }
377 }
378
hbosc82f2e12016-09-05 01:36:50 -0700379 protected:
380 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
381 rtc::scoped_refptr<RTCStatsCollector> collector_;
382};
383
384TEST_F(RTCStatsCollectorTest, SingleCallback) {
385 rtc::scoped_refptr<const RTCStatsReport> result;
386 collector_->GetStatsReport(StatsCallback::Create(&result));
387 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
388}
389
390TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
391 rtc::scoped_refptr<const RTCStatsReport> a;
392 rtc::scoped_refptr<const RTCStatsReport> b;
393 rtc::scoped_refptr<const RTCStatsReport> c;
394 collector_->GetStatsReport(StatsCallback::Create(&a));
395 collector_->GetStatsReport(StatsCallback::Create(&b));
396 collector_->GetStatsReport(StatsCallback::Create(&c));
397 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
398 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
399 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
400 EXPECT_EQ(a.get(), b.get());
401 EXPECT_EQ(b.get(), c.get());
402}
403
404TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700405 // Caching should ensure |a| and |b| are the same report.
hbosc82f2e12016-09-05 01:36:50 -0700406 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
407 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700408 EXPECT_EQ(a.get(), b.get());
409 // Invalidate cache by clearing it.
hbosc82f2e12016-09-05 01:36:50 -0700410 collector_->ClearCachedStatsReport();
411 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700412 EXPECT_NE(b.get(), c.get());
413 // Invalidate cache by advancing time.
hbosfdafab82016-09-14 06:02:13 -0700414 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700415 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700416 EXPECT_TRUE(d);
417 EXPECT_NE(c.get(), d.get());
418}
419
hbosc82f2e12016-09-05 01:36:50 -0700420TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
hbosc82f2e12016-09-05 01:36:50 -0700421 rtc::scoped_refptr<const RTCStatsReport> a;
422 rtc::scoped_refptr<const RTCStatsReport> b;
423 rtc::scoped_refptr<const RTCStatsReport> c;
424 collector_->GetStatsReport(StatsCallback::Create(&a));
425 collector_->GetStatsReport(StatsCallback::Create(&b));
426 // Cache is invalidated after 50 ms.
hbosfdafab82016-09-14 06:02:13 -0700427 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700428 collector_->GetStatsReport(StatsCallback::Create(&c));
429 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
430 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
431 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
432 EXPECT_EQ(a.get(), b.get());
433 // The act of doing |AdvanceTime| processes all messages. If this was not the
434 // case we might not require |c| to be fresher than |b|.
435 EXPECT_NE(c.get(), b.get());
436}
437
hbos6ab97ce2016-10-03 14:16:56 -0700438TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
439 std::unique_ptr<CertificateInfo> local_certinfo =
440 CreateFakeCertificateAndInfoFromDers(
441 std::vector<std::string>({ "(local) single certificate" }));
442 std::unique_ptr<CertificateInfo> remote_certinfo =
443 CreateFakeCertificateAndInfoFromDers(
444 std::vector<std::string>({ "(remote) single certificate" }));
445
446 // Mock the session to return the local and remote certificates.
447 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
448 [this](SessionStats* stats) {
449 stats->transport_stats["transport"].transport_name = "transport";
450 return true;
451 }));
452 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
453 Invoke([this, &local_certinfo](const std::string& transport_name,
454 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
455 if (transport_name == "transport") {
456 *certificate = local_certinfo->certificate;
457 return true;
458 }
459 return false;
460 }));
461 EXPECT_CALL(test_->session(),
462 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
463 [this, &remote_certinfo](const std::string& transport_name) {
464 if (transport_name == "transport")
465 return remote_certinfo->certificate->ssl_certificate().GetReference();
466 return static_cast<rtc::SSLCertificate*>(nullptr);
467 }));
468
469 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
470 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
471 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
472}
473
474TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
475 std::unique_ptr<CertificateInfo> audio_local_certinfo =
476 CreateFakeCertificateAndInfoFromDers(
477 std::vector<std::string>({ "(local) audio" }));
478 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
479 audio_local_certinfo->ders);
480 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
481 CreateFakeCertificateAndInfoFromDers(
482 std::vector<std::string>({ "(remote) audio" }));
483 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
484 audio_remote_certinfo->ders);
485
486 std::unique_ptr<CertificateInfo> video_local_certinfo =
487 CreateFakeCertificateAndInfoFromDers(
488 std::vector<std::string>({ "(local) video" }));
489 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
490 video_local_certinfo->ders);
491 std::unique_ptr<CertificateInfo> video_remote_certinfo =
492 CreateFakeCertificateAndInfoFromDers(
493 std::vector<std::string>({ "(remote) video" }));
494 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
495 video_remote_certinfo->ders);
496
497 // Mock the session to return the local and remote certificates.
498 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
499 [this](SessionStats* stats) {
500 stats->transport_stats["audio"].transport_name = "audio";
501 stats->transport_stats["video"].transport_name = "video";
502 return true;
503 }));
504 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
505 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
506 const std::string& transport_name,
507 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
508 if (transport_name == "audio") {
509 *certificate = audio_local_certinfo->certificate;
510 return true;
511 }
512 if (transport_name == "video") {
513 *certificate = video_local_certinfo->certificate;
514 return true;
515 }
516 return false;
517 }));
518 EXPECT_CALL(test_->session(),
519 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
520 [this, &audio_remote_certinfo, &video_remote_certinfo](
521 const std::string& transport_name) {
522 if (transport_name == "audio") {
523 return audio_remote_certinfo->certificate->ssl_certificate()
524 .GetReference();
525 }
526 if (transport_name == "video") {
527 return video_remote_certinfo->certificate->ssl_certificate()
528 .GetReference();
529 }
530 return static_cast<rtc::SSLCertificate*>(nullptr);
531 }));
532
533 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
534 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
535 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
536 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
537 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
538}
539
540TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
541 std::vector<std::string> local_ders;
542 local_ders.push_back("(local) this");
543 local_ders.push_back("(local) is");
544 local_ders.push_back("(local) a");
545 local_ders.push_back("(local) chain");
546 std::unique_ptr<CertificateInfo> local_certinfo =
547 CreateFakeCertificateAndInfoFromDers(local_ders);
548 std::vector<std::string> remote_ders;
549 remote_ders.push_back("(remote) this");
550 remote_ders.push_back("(remote) is");
551 remote_ders.push_back("(remote) another");
552 remote_ders.push_back("(remote) chain");
553 std::unique_ptr<CertificateInfo> remote_certinfo =
554 CreateFakeCertificateAndInfoFromDers(remote_ders);
555
556 // Mock the session to return the local and remote certificates.
557 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
558 [this](SessionStats* stats) {
559 stats->transport_stats["transport"].transport_name = "transport";
560 return true;
561 }));
562 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
563 Invoke([this, &local_certinfo](const std::string& transport_name,
564 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
565 if (transport_name == "transport") {
566 *certificate = local_certinfo->certificate;
567 return true;
568 }
569 return false;
570 }));
571 EXPECT_CALL(test_->session(),
572 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
573 [this, &remote_certinfo](const std::string& transport_name) {
574 if (transport_name == "transport")
575 return remote_certinfo->certificate->ssl_certificate().GetReference();
576 return static_cast<rtc::SSLCertificate*>(nullptr);
577 }));
578
579 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
580 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
581 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
582}
583
hbosab9f6e42016-10-07 02:18:47 -0700584TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
585 // Candidates in the first transport stats.
586 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
587 "1.2.3.4", 5,
588 "a_local_host's protocol",
589 cricket::LOCAL_PORT_TYPE,
590 0);
591 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
592 "6.7.8.9", 10,
593 "remote_srflx's protocol",
594 cricket::STUN_PORT_TYPE,
595 1);
596 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
597 "11.12.13.14", 15,
598 "a_local_prflx's protocol",
599 cricket::PRFLX_PORT_TYPE,
600 2);
601 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
602 "16.17.18.19", 20,
603 "a_remote_relay's protocol",
604 cricket::RELAY_PORT_TYPE,
605 3);
606 // Candidates in the second transport stats.
607 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate(
608 "42.42.42.42", 42,
609 "b_local's protocol",
610 cricket::LOCAL_PORT_TYPE,
611 42);
612 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
613 "42.42.42.42", 42,
614 "b_remote's protocol",
615 cricket::LOCAL_PORT_TYPE,
616 42);
617
618 SessionStats session_stats;
619
620 cricket::TransportChannelStats a_transport_channel_stats;
621 a_transport_channel_stats.connection_infos.push_back(
622 cricket::ConnectionInfo());
623 a_transport_channel_stats.connection_infos[0].local_candidate =
624 *a_local_host.get();
625 a_transport_channel_stats.connection_infos[0].remote_candidate =
626 *a_remote_srflx.get();
627 a_transport_channel_stats.connection_infos.push_back(
628 cricket::ConnectionInfo());
629 a_transport_channel_stats.connection_infos[1].local_candidate =
630 *a_local_prflx.get();
631 a_transport_channel_stats.connection_infos[1].remote_candidate =
632 *a_remote_relay.get();
633 session_stats.transport_stats["a"].channel_stats.push_back(
634 a_transport_channel_stats);
635
636 cricket::TransportChannelStats b_transport_channel_stats;
637 b_transport_channel_stats.connection_infos.push_back(
638 cricket::ConnectionInfo());
639 b_transport_channel_stats.connection_infos[0].local_candidate =
640 *b_local.get();
641 b_transport_channel_stats.connection_infos[0].remote_candidate =
642 *b_remote.get();
643 session_stats.transport_stats["b"].channel_stats.push_back(
644 b_transport_channel_stats);
645
646 // Mock the session to return the desired candidates.
647 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
648 [this, &session_stats](SessionStats* stats) {
649 *stats = session_stats;
650 return true;
651 }));
652
653 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
654 ExpectReportContainsCandidate(report, *a_local_host.get(), true);
655 ExpectReportContainsCandidate(report, *a_remote_srflx.get(), false);
656 ExpectReportContainsCandidate(report, *a_local_prflx.get(), true);
657 ExpectReportContainsCandidate(report, *a_remote_relay.get(), false);
658 ExpectReportContainsCandidate(report, *b_local.get(), true);
659 ExpectReportContainsCandidate(report, *b_remote.get(), false);
660}
661
hbosd565b732016-08-30 14:04:35 -0700662TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
nissecdf37a92016-09-13 23:41:47 -0700663 int64_t before = rtc::TimeUTCMicros();
hbosc82f2e12016-09-05 01:36:50 -0700664 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
nissecdf37a92016-09-13 23:41:47 -0700665 int64_t after = rtc::TimeUTCMicros();
hbosd565b732016-08-30 14:04:35 -0700666 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
667 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
668 const RTCStats* stats = report->Get("RTCPeerConnection");
669 EXPECT_TRUE(stats);
hbos0e6758d2016-08-31 07:57:36 -0700670 EXPECT_LE(before, stats->timestamp_us());
671 EXPECT_LE(stats->timestamp_us(), after);
hbosd565b732016-08-30 14:04:35 -0700672 {
673 // Expected stats with no data channels
674 const RTCPeerConnectionStats& pcstats =
675 stats->cast_to<RTCPeerConnectionStats>();
676 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0));
677 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0));
678 }
679
680 test_->data_channels().push_back(
681 new MockDataChannel(DataChannelInterface::kConnecting));
682 test_->data_channels().push_back(
683 new MockDataChannel(DataChannelInterface::kOpen));
684 test_->data_channels().push_back(
685 new MockDataChannel(DataChannelInterface::kClosing));
686 test_->data_channels().push_back(
687 new MockDataChannel(DataChannelInterface::kClosed));
688
hbosc82f2e12016-09-05 01:36:50 -0700689 collector_->ClearCachedStatsReport();
690 report = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700691 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
692 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
693 stats = report->Get("RTCPeerConnection");
694 EXPECT_TRUE(stats);
695 {
696 // Expected stats with the above four data channels
697 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data
698 // channels that have been opened and closed, not the numbers currently
699 // open/closed, we would expect opened >= closed and (opened - closed) to be
700 // the number currently open. crbug.com/636818.
701 const RTCPeerConnectionStats& pcstats =
702 stats->cast_to<RTCPeerConnectionStats>();
703 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1));
704 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3));
705 }
706}
707
hbosc82f2e12016-09-05 01:36:50 -0700708class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
709 public:
710 RTCStatsCollectorTestWithFakeCollector()
711 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
712 collector_(FakeRTCStatsCollector::Create(
713 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
714 }
715
716 protected:
717 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
718 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
719};
720
721TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
722 collector_->VerifyThreadUsageAndResultsMerging();
723}
724
725} // namespace
726
hbosd565b732016-08-30 14:04:35 -0700727} // namespace webrtc