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