blob: c8eed9febbaed7c84e9411dabfb1173488b6d468 [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
hbosc47a0c32016-10-11 14:54:49 -0700334 const RTCIceCandidateStats* ExpectReportContainsCandidate(
hbosab9f6e42016-10-07 02:18:47 -0700335 const rtc::scoped_refptr<const RTCStatsReport>& report,
336 const cricket::Candidate& candidate,
337 bool is_local) {
hbosc47a0c32016-10-11 14:54:49 -0700338 const RTCStats* stats = report->Get("RTCIceCandidate_" + candidate.id());
hbosab9f6e42016-10-07 02:18:47 -0700339 EXPECT_TRUE(stats);
340 const RTCIceCandidateStats* candidate_stats;
341 if (is_local)
342 candidate_stats = &stats->cast_to<RTCLocalIceCandidateStats>();
343 else
344 candidate_stats = &stats->cast_to<RTCRemoteIceCandidateStats>();
345 EXPECT_EQ(*candidate_stats->ip, candidate.address().ipaddr().ToString());
346 EXPECT_EQ(*candidate_stats->port,
347 static_cast<int32_t>(candidate.address().port()));
348 EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
349 EXPECT_EQ(*candidate_stats->candidate_type,
350 CandidateTypeToRTCIceCandidateType(candidate.type()));
351 EXPECT_EQ(*candidate_stats->priority,
352 static_cast<int32_t>(candidate.priority()));
353 // TODO(hbos): Define candidate_stats->url. crbug.com/632723
354 EXPECT_FALSE(candidate_stats->url.is_defined());
hbosc47a0c32016-10-11 14:54:49 -0700355 return candidate_stats;
356 }
357
358 void ExpectReportContainsCandidatePair(
359 const rtc::scoped_refptr<const RTCStatsReport>& report,
360 const cricket::TransportStats& transport_stats) {
361 for (const auto& channel_stats : transport_stats.channel_stats) {
362 for (const cricket::ConnectionInfo& info :
363 channel_stats.connection_infos) {
364 const std::string& id = "RTCIceCandidatePair_" +
365 info.local_candidate.id() + "_" + info.remote_candidate.id();
366 const RTCStats* stats = report->Get(id);
367 EXPECT_TRUE(stats);
368 const RTCIceCandidatePairStats& candidate_pair_stats =
369 stats->cast_to<RTCIceCandidatePairStats>();
370
371 // TODO(hbos): Define all the undefined |candidate_pair_stats| stats.
372 // The EXPECT_FALSE are for the undefined stats, see also todos listed
373 // in rtcstatscollector.cc. crbug.com/633550
374 EXPECT_FALSE(candidate_pair_stats.transport_id.is_defined());
375 const RTCIceCandidateStats* local_candidate =
376 ExpectReportContainsCandidate(report, info.local_candidate, true);
377 EXPECT_EQ(*candidate_pair_stats.local_candidate_id,
378 local_candidate->id());
379 const RTCIceCandidateStats* remote_candidate =
380 ExpectReportContainsCandidate(report, info.remote_candidate, false);
381 EXPECT_EQ(*candidate_pair_stats.remote_candidate_id,
382 remote_candidate->id());
383
384 EXPECT_FALSE(candidate_pair_stats.state.is_defined());
385 EXPECT_FALSE(candidate_pair_stats.priority.is_defined());
386 EXPECT_FALSE(candidate_pair_stats.nominated.is_defined());
387 EXPECT_EQ(*candidate_pair_stats.writable, info.writable);
388 EXPECT_FALSE(candidate_pair_stats.readable.is_defined());
389 EXPECT_EQ(*candidate_pair_stats.bytes_sent,
390 static_cast<uint64_t>(info.sent_total_bytes));
391 EXPECT_EQ(*candidate_pair_stats.bytes_received,
392 static_cast<uint64_t>(info.recv_total_bytes));
393 EXPECT_FALSE(candidate_pair_stats.total_rtt.is_defined());
394 EXPECT_EQ(*candidate_pair_stats.current_rtt,
395 static_cast<double>(info.rtt) / 1000.0);
396 EXPECT_FALSE(
397 candidate_pair_stats.available_outgoing_bitrate.is_defined());
398 EXPECT_FALSE(
399 candidate_pair_stats.available_incoming_bitrate.is_defined());
400 EXPECT_FALSE(candidate_pair_stats.requests_received.is_defined());
401 EXPECT_EQ(*candidate_pair_stats.requests_sent,
402 static_cast<uint64_t>(info.sent_ping_requests_total));
403 EXPECT_EQ(*candidate_pair_stats.responses_received,
404 static_cast<uint64_t>(info.recv_ping_responses));
405 EXPECT_EQ(*candidate_pair_stats.responses_sent,
406 static_cast<uint64_t>(info.sent_ping_responses));
407 EXPECT_FALSE(
408 candidate_pair_stats.retransmissions_received.is_defined());
409 EXPECT_FALSE(candidate_pair_stats.retransmissions_sent.is_defined());
410 EXPECT_FALSE(
411 candidate_pair_stats.consent_requests_received.is_defined());
412 EXPECT_FALSE(candidate_pair_stats.consent_requests_sent.is_defined());
413 EXPECT_FALSE(
414 candidate_pair_stats.consent_responses_received.is_defined());
415 EXPECT_FALSE(candidate_pair_stats.consent_responses_sent.is_defined());
416 }
417 }
hbosab9f6e42016-10-07 02:18:47 -0700418 }
419
hbos6ab97ce2016-10-03 14:16:56 -0700420 void ExpectReportContainsCertificateInfo(
421 const rtc::scoped_refptr<const RTCStatsReport>& report,
422 const CertificateInfo& cert_info) {
423 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
424 const RTCStats* stats = report->Get(
425 "RTCCertificate_" + cert_info.fingerprints[i]);
426 EXPECT_TRUE(stats);
427 const RTCCertificateStats& cert_stats =
428 stats->cast_to<const RTCCertificateStats>();
429 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
430 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
431 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
432 if (i + 1 < cert_info.fingerprints.size()) {
433 EXPECT_EQ(*cert_stats.issuer_certificate_id,
434 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
435 } else {
436 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
437 }
438 }
439 }
440
hbosc82f2e12016-09-05 01:36:50 -0700441 protected:
442 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
443 rtc::scoped_refptr<RTCStatsCollector> collector_;
444};
445
446TEST_F(RTCStatsCollectorTest, SingleCallback) {
447 rtc::scoped_refptr<const RTCStatsReport> result;
448 collector_->GetStatsReport(StatsCallback::Create(&result));
449 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
450}
451
452TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
453 rtc::scoped_refptr<const RTCStatsReport> a;
454 rtc::scoped_refptr<const RTCStatsReport> b;
455 rtc::scoped_refptr<const RTCStatsReport> c;
456 collector_->GetStatsReport(StatsCallback::Create(&a));
457 collector_->GetStatsReport(StatsCallback::Create(&b));
458 collector_->GetStatsReport(StatsCallback::Create(&c));
459 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
460 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
461 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
462 EXPECT_EQ(a.get(), b.get());
463 EXPECT_EQ(b.get(), c.get());
464}
465
466TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700467 // Caching should ensure |a| and |b| are the same report.
hbosc82f2e12016-09-05 01:36:50 -0700468 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
469 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700470 EXPECT_EQ(a.get(), b.get());
471 // Invalidate cache by clearing it.
hbosc82f2e12016-09-05 01:36:50 -0700472 collector_->ClearCachedStatsReport();
473 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700474 EXPECT_NE(b.get(), c.get());
475 // Invalidate cache by advancing time.
hbosfdafab82016-09-14 06:02:13 -0700476 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700477 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700478 EXPECT_TRUE(d);
479 EXPECT_NE(c.get(), d.get());
480}
481
hbosc82f2e12016-09-05 01:36:50 -0700482TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
hbosc82f2e12016-09-05 01:36:50 -0700483 rtc::scoped_refptr<const RTCStatsReport> a;
484 rtc::scoped_refptr<const RTCStatsReport> b;
485 rtc::scoped_refptr<const RTCStatsReport> c;
486 collector_->GetStatsReport(StatsCallback::Create(&a));
487 collector_->GetStatsReport(StatsCallback::Create(&b));
488 // Cache is invalidated after 50 ms.
hbosfdafab82016-09-14 06:02:13 -0700489 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700490 collector_->GetStatsReport(StatsCallback::Create(&c));
491 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
492 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
493 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
494 EXPECT_EQ(a.get(), b.get());
495 // The act of doing |AdvanceTime| processes all messages. If this was not the
496 // case we might not require |c| to be fresher than |b|.
497 EXPECT_NE(c.get(), b.get());
498}
499
hbos6ab97ce2016-10-03 14:16:56 -0700500TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
501 std::unique_ptr<CertificateInfo> local_certinfo =
502 CreateFakeCertificateAndInfoFromDers(
503 std::vector<std::string>({ "(local) single certificate" }));
504 std::unique_ptr<CertificateInfo> remote_certinfo =
505 CreateFakeCertificateAndInfoFromDers(
506 std::vector<std::string>({ "(remote) single certificate" }));
507
508 // Mock the session to return the local and remote certificates.
509 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
510 [this](SessionStats* stats) {
511 stats->transport_stats["transport"].transport_name = "transport";
512 return true;
513 }));
514 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
515 Invoke([this, &local_certinfo](const std::string& transport_name,
516 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
517 if (transport_name == "transport") {
518 *certificate = local_certinfo->certificate;
519 return true;
520 }
521 return false;
522 }));
523 EXPECT_CALL(test_->session(),
524 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
525 [this, &remote_certinfo](const std::string& transport_name) {
526 if (transport_name == "transport")
527 return remote_certinfo->certificate->ssl_certificate().GetReference();
528 return static_cast<rtc::SSLCertificate*>(nullptr);
529 }));
530
531 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
532 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
533 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
534}
535
536TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
537 std::unique_ptr<CertificateInfo> audio_local_certinfo =
538 CreateFakeCertificateAndInfoFromDers(
539 std::vector<std::string>({ "(local) audio" }));
540 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
541 audio_local_certinfo->ders);
542 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
543 CreateFakeCertificateAndInfoFromDers(
544 std::vector<std::string>({ "(remote) audio" }));
545 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
546 audio_remote_certinfo->ders);
547
548 std::unique_ptr<CertificateInfo> video_local_certinfo =
549 CreateFakeCertificateAndInfoFromDers(
550 std::vector<std::string>({ "(local) video" }));
551 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
552 video_local_certinfo->ders);
553 std::unique_ptr<CertificateInfo> video_remote_certinfo =
554 CreateFakeCertificateAndInfoFromDers(
555 std::vector<std::string>({ "(remote) video" }));
556 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
557 video_remote_certinfo->ders);
558
559 // Mock the session to return the local and remote certificates.
560 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
561 [this](SessionStats* stats) {
562 stats->transport_stats["audio"].transport_name = "audio";
563 stats->transport_stats["video"].transport_name = "video";
564 return true;
565 }));
566 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
567 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
568 const std::string& transport_name,
569 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
570 if (transport_name == "audio") {
571 *certificate = audio_local_certinfo->certificate;
572 return true;
573 }
574 if (transport_name == "video") {
575 *certificate = video_local_certinfo->certificate;
576 return true;
577 }
578 return false;
579 }));
580 EXPECT_CALL(test_->session(),
581 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
582 [this, &audio_remote_certinfo, &video_remote_certinfo](
583 const std::string& transport_name) {
584 if (transport_name == "audio") {
585 return audio_remote_certinfo->certificate->ssl_certificate()
586 .GetReference();
587 }
588 if (transport_name == "video") {
589 return video_remote_certinfo->certificate->ssl_certificate()
590 .GetReference();
591 }
592 return static_cast<rtc::SSLCertificate*>(nullptr);
593 }));
594
595 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
596 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
597 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
598 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
599 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
600}
601
602TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
603 std::vector<std::string> local_ders;
604 local_ders.push_back("(local) this");
605 local_ders.push_back("(local) is");
606 local_ders.push_back("(local) a");
607 local_ders.push_back("(local) chain");
608 std::unique_ptr<CertificateInfo> local_certinfo =
609 CreateFakeCertificateAndInfoFromDers(local_ders);
610 std::vector<std::string> remote_ders;
611 remote_ders.push_back("(remote) this");
612 remote_ders.push_back("(remote) is");
613 remote_ders.push_back("(remote) another");
614 remote_ders.push_back("(remote) chain");
615 std::unique_ptr<CertificateInfo> remote_certinfo =
616 CreateFakeCertificateAndInfoFromDers(remote_ders);
617
618 // Mock the session to return the local and remote certificates.
619 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
620 [this](SessionStats* stats) {
621 stats->transport_stats["transport"].transport_name = "transport";
622 return true;
623 }));
624 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
625 Invoke([this, &local_certinfo](const std::string& transport_name,
626 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
627 if (transport_name == "transport") {
628 *certificate = local_certinfo->certificate;
629 return true;
630 }
631 return false;
632 }));
633 EXPECT_CALL(test_->session(),
634 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
635 [this, &remote_certinfo](const std::string& transport_name) {
636 if (transport_name == "transport")
637 return remote_certinfo->certificate->ssl_certificate().GetReference();
638 return static_cast<rtc::SSLCertificate*>(nullptr);
639 }));
640
641 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
642 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
643 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
644}
645
hbosab9f6e42016-10-07 02:18:47 -0700646TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
647 // Candidates in the first transport stats.
648 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
649 "1.2.3.4", 5,
650 "a_local_host's protocol",
651 cricket::LOCAL_PORT_TYPE,
652 0);
653 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
654 "6.7.8.9", 10,
655 "remote_srflx's protocol",
656 cricket::STUN_PORT_TYPE,
657 1);
658 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
659 "11.12.13.14", 15,
660 "a_local_prflx's protocol",
661 cricket::PRFLX_PORT_TYPE,
662 2);
663 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
664 "16.17.18.19", 20,
665 "a_remote_relay's protocol",
666 cricket::RELAY_PORT_TYPE,
667 3);
668 // Candidates in the second transport stats.
669 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate(
670 "42.42.42.42", 42,
671 "b_local's protocol",
672 cricket::LOCAL_PORT_TYPE,
673 42);
674 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
675 "42.42.42.42", 42,
676 "b_remote's protocol",
677 cricket::LOCAL_PORT_TYPE,
678 42);
679
680 SessionStats session_stats;
681
682 cricket::TransportChannelStats a_transport_channel_stats;
683 a_transport_channel_stats.connection_infos.push_back(
684 cricket::ConnectionInfo());
685 a_transport_channel_stats.connection_infos[0].local_candidate =
686 *a_local_host.get();
687 a_transport_channel_stats.connection_infos[0].remote_candidate =
688 *a_remote_srflx.get();
689 a_transport_channel_stats.connection_infos.push_back(
690 cricket::ConnectionInfo());
691 a_transport_channel_stats.connection_infos[1].local_candidate =
692 *a_local_prflx.get();
693 a_transport_channel_stats.connection_infos[1].remote_candidate =
694 *a_remote_relay.get();
695 session_stats.transport_stats["a"].channel_stats.push_back(
696 a_transport_channel_stats);
697
698 cricket::TransportChannelStats b_transport_channel_stats;
699 b_transport_channel_stats.connection_infos.push_back(
700 cricket::ConnectionInfo());
701 b_transport_channel_stats.connection_infos[0].local_candidate =
702 *b_local.get();
703 b_transport_channel_stats.connection_infos[0].remote_candidate =
704 *b_remote.get();
705 session_stats.transport_stats["b"].channel_stats.push_back(
706 b_transport_channel_stats);
707
708 // Mock the session to return the desired candidates.
709 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
710 [this, &session_stats](SessionStats* stats) {
711 *stats = session_stats;
712 return true;
713 }));
714
715 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
716 ExpectReportContainsCandidate(report, *a_local_host.get(), true);
717 ExpectReportContainsCandidate(report, *a_remote_srflx.get(), false);
718 ExpectReportContainsCandidate(report, *a_local_prflx.get(), true);
719 ExpectReportContainsCandidate(report, *a_remote_relay.get(), false);
720 ExpectReportContainsCandidate(report, *b_local.get(), true);
721 ExpectReportContainsCandidate(report, *b_remote.get(), false);
722}
723
hbosc47a0c32016-10-11 14:54:49 -0700724TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
725 std::unique_ptr<cricket::Candidate> local_candidate = CreateFakeCandidate(
726 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
727 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
728 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
729
730 SessionStats session_stats;
731
732 cricket::ConnectionInfo connection_info;
733 connection_info.local_candidate = *local_candidate.get();
734 connection_info.remote_candidate = *remote_candidate.get();
735 connection_info.writable = true;
736 connection_info.sent_total_bytes = 42;
737 connection_info.recv_total_bytes = 1234;
738 connection_info.rtt = 1337;
739 connection_info.sent_ping_requests_total = 1010;
740 connection_info.recv_ping_responses = 4321;
741 connection_info.sent_ping_responses = 1000;
742
743 cricket::TransportChannelStats transport_channel_stats;
744 transport_channel_stats.connection_infos.push_back(connection_info);
745 session_stats.transport_stats["transport"].transport_name = "transport";
746 session_stats.transport_stats["transport"].channel_stats.push_back(
747 transport_channel_stats);
748
749 // Mock the session to return the desired candidates.
750 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
751 [this, &session_stats](SessionStats* stats) {
752 *stats = session_stats;
753 return true;
754 }));
755
756 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
757 ExpectReportContainsCandidatePair(
758 report, session_stats.transport_stats["transport"]);
759}
760
hbosd565b732016-08-30 14:04:35 -0700761TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
nissecdf37a92016-09-13 23:41:47 -0700762 int64_t before = rtc::TimeUTCMicros();
hbosc82f2e12016-09-05 01:36:50 -0700763 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
nissecdf37a92016-09-13 23:41:47 -0700764 int64_t after = rtc::TimeUTCMicros();
hbosd565b732016-08-30 14:04:35 -0700765 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
766 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
767 const RTCStats* stats = report->Get("RTCPeerConnection");
768 EXPECT_TRUE(stats);
hbos0e6758d2016-08-31 07:57:36 -0700769 EXPECT_LE(before, stats->timestamp_us());
770 EXPECT_LE(stats->timestamp_us(), after);
hbosd565b732016-08-30 14:04:35 -0700771 {
772 // Expected stats with no data channels
773 const RTCPeerConnectionStats& pcstats =
774 stats->cast_to<RTCPeerConnectionStats>();
775 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0));
776 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0));
777 }
778
779 test_->data_channels().push_back(
780 new MockDataChannel(DataChannelInterface::kConnecting));
781 test_->data_channels().push_back(
782 new MockDataChannel(DataChannelInterface::kOpen));
783 test_->data_channels().push_back(
784 new MockDataChannel(DataChannelInterface::kClosing));
785 test_->data_channels().push_back(
786 new MockDataChannel(DataChannelInterface::kClosed));
787
hbosc82f2e12016-09-05 01:36:50 -0700788 collector_->ClearCachedStatsReport();
789 report = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700790 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
791 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
792 stats = report->Get("RTCPeerConnection");
793 EXPECT_TRUE(stats);
794 {
795 // Expected stats with the above four data channels
796 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data
797 // channels that have been opened and closed, not the numbers currently
798 // open/closed, we would expect opened >= closed and (opened - closed) to be
799 // the number currently open. crbug.com/636818.
800 const RTCPeerConnectionStats& pcstats =
801 stats->cast_to<RTCPeerConnectionStats>();
802 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1));
803 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3));
804 }
805}
806
hbosc82f2e12016-09-05 01:36:50 -0700807class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
808 public:
809 RTCStatsCollectorTestWithFakeCollector()
810 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
811 collector_(FakeRTCStatsCollector::Create(
812 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
813 }
814
815 protected:
816 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
817 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
818};
819
820TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
821 collector_->VerifyThreadUsageAndResultsMerging();
822}
823
824} // namespace
825
hbosd565b732016-08-30 14:04:35 -0700826} // namespace webrtc