blob: 97ede90207176fb3f986703ac871b676868283f1 [file] [log] [blame]
hbosd565b732016-08-30 14:04:35 -07001/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
hbos74e1a4f2016-09-15 23:33:01 -070011#include "webrtc/api/rtcstatscollector.h"
hbosd565b732016-08-30 14:04:35 -070012
13#include <memory>
hbosda389e32016-10-25 10:55:08 -070014#include <ostream>
hbosd565b732016-08-30 14:04:35 -070015#include <string>
16#include <vector>
17
18#include "webrtc/api/jsepsessiondescription.h"
hbos74e1a4f2016-09-15 23:33:01 -070019#include "webrtc/api/stats/rtcstats_objects.h"
20#include "webrtc/api/stats/rtcstatsreport.h"
hbosd565b732016-08-30 14:04:35 -070021#include "webrtc/api/test/mock_datachannel.h"
22#include "webrtc/api/test/mock_peerconnection.h"
23#include "webrtc/api/test/mock_webrtcsession.h"
24#include "webrtc/base/checks.h"
hbos0e6758d2016-08-31 07:57:36 -070025#include "webrtc/base/fakeclock.h"
hbos6ab97ce2016-10-03 14:16:56 -070026#include "webrtc/base/fakesslidentity.h"
hbosd565b732016-08-30 14:04:35 -070027#include "webrtc/base/gunit.h"
28#include "webrtc/base/logging.h"
hbosab9f6e42016-10-07 02:18:47 -070029#include "webrtc/base/socketaddress.h"
hbosc82f2e12016-09-05 01:36:50 -070030#include "webrtc/base/thread_checker.h"
hbos0e6758d2016-08-31 07:57:36 -070031#include "webrtc/base/timedelta.h"
32#include "webrtc/base/timeutils.h"
skvlad11a9cbf2016-10-07 11:53:05 -070033#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
hbosd565b732016-08-30 14:04:35 -070034#include "webrtc/media/base/fakemediaengine.h"
hbos2fa7c672016-10-24 04:00:05 -070035#include "webrtc/p2p/base/p2pconstants.h"
hbosab9f6e42016-10-07 02:18:47 -070036#include "webrtc/p2p/base/port.h"
hbosd565b732016-08-30 14:04:35 -070037
hbos6ab97ce2016-10-03 14:16:56 -070038using testing::_;
39using testing::Invoke;
hbosd565b732016-08-30 14:04:35 -070040using testing::Return;
41using testing::ReturnRef;
42
43namespace webrtc {
44
hbosda389e32016-10-25 10:55:08 -070045// These are used by gtest code, such as if |EXPECT_EQ| fails.
46void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
47 *os << stats.ToString();
48}
49
50void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
51 *os << stats.ToString();
52}
53
54void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
55 *os << stats.ToString();
56}
57
58void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
59 *os << stats.ToString();
60}
61
62void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
63 *os << stats.ToString();
64}
65
66void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
67 *os << stats.ToString();
68}
69
70void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
71 *os << stats.ToString();
72}
73
hbosc82f2e12016-09-05 01:36:50 -070074namespace {
75
76const int64_t kGetStatsReportTimeoutMs = 1000;
77
hbos6ab97ce2016-10-03 14:16:56 -070078struct CertificateInfo {
79 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
80 std::vector<std::string> ders;
81 std::vector<std::string> pems;
82 std::vector<std::string> fingerprints;
83};
84
85std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
86 const std::vector<std::string>& ders) {
87 RTC_CHECK(!ders.empty());
88 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
89 info->ders = ders;
90 for (const std::string& der : ders) {
91 info->pems.push_back(rtc::SSLIdentity::DerToPem(
92 "CERTIFICATE",
93 reinterpret_cast<const unsigned char*>(der.c_str()),
94 der.length()));
95 }
96 info->certificate =
97 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
98 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
99 // Strip header/footer and newline characters of PEM strings.
100 for (size_t i = 0; i < info->pems.size(); ++i) {
101 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
102 "", 0, &info->pems[i]);
103 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
104 "", 0, &info->pems[i]);
105 rtc::replace_substrs("\n", 1,
106 "", 0, &info->pems[i]);
107 }
108 // Fingerprint of leaf certificate.
109 std::unique_ptr<rtc::SSLFingerprint> fp(
110 rtc::SSLFingerprint::Create("sha-1",
111 &info->certificate->ssl_certificate()));
112 EXPECT_TRUE(fp);
113 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
114 // Fingerprints of the rest of the chain.
115 std::unique_ptr<rtc::SSLCertChain> chain =
116 info->certificate->ssl_certificate().GetChain();
117 if (chain) {
118 for (size_t i = 0; i < chain->GetSize(); i++) {
119 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
120 EXPECT_TRUE(fp);
121 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
122 }
123 }
124 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
125 return info;
126}
127
hbosab9f6e42016-10-07 02:18:47 -0700128std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
129 const std::string& hostname,
130 int port,
131 const std::string& protocol,
132 const std::string& candidate_type,
133 uint32_t priority) {
134 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
135 candidate->set_address(rtc::SocketAddress(hostname, port));
136 candidate->set_protocol(protocol);
137 candidate->set_type(candidate_type);
138 candidate->set_priority(priority);
139 return candidate;
140}
141
hbosc82f2e12016-09-05 01:36:50 -0700142class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
hbosd565b732016-08-30 14:04:35 -0700143 public:
hbosc82f2e12016-09-05 01:36:50 -0700144 RTCStatsCollectorTestHelper()
hbosd565b732016-08-30 14:04:35 -0700145 : worker_thread_(rtc::Thread::Current()),
146 network_thread_(rtc::Thread::Current()),
skvlad11a9cbf2016-10-07 11:53:05 -0700147 channel_manager_(
148 new cricket::ChannelManager(new cricket::FakeMediaEngine(),
149 worker_thread_,
150 network_thread_)),
hbosd565b732016-08-30 14:04:35 -0700151 media_controller_(
152 MediaControllerInterface::Create(cricket::MediaConfig(),
153 worker_thread_,
skvlad11a9cbf2016-10-07 11:53:05 -0700154 channel_manager_.get(),
155 &event_log_)),
hbosd565b732016-08-30 14:04:35 -0700156 session_(media_controller_.get()),
157 pc_() {
hbos6ab97ce2016-10-03 14:16:56 -0700158 // Default return values for mocks.
hbosd565b732016-08-30 14:04:35 -0700159 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
160 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
161 ReturnRef(data_channels_));
hbos6ab97ce2016-10-03 14:16:56 -0700162 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
hbosab9f6e42016-10-07 02:18:47 -0700163 EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly(
164 Return(false));
165 EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_))
166 .WillRepeatedly(Return(nullptr));
hbosd565b732016-08-30 14:04:35 -0700167 }
168
hbosfdafab82016-09-14 06:02:13 -0700169 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; }
hbosd565b732016-08-30 14:04:35 -0700170 MockWebRtcSession& session() { return session_; }
171 MockPeerConnection& pc() { return pc_; }
172 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() {
173 return data_channels_;
174 }
175
176 // SetSessionDescriptionObserver overrides.
177 void OnSuccess() override {}
178 void OnFailure(const std::string& error) override {
179 RTC_NOTREACHED() << error;
180 }
181
182 private:
hbosfdafab82016-09-14 06:02:13 -0700183 rtc::ScopedFakeClock fake_clock_;
skvlad11a9cbf2016-10-07 11:53:05 -0700184 webrtc::RtcEventLogNullImpl event_log_;
hbosd565b732016-08-30 14:04:35 -0700185 rtc::Thread* const worker_thread_;
186 rtc::Thread* const network_thread_;
187 std::unique_ptr<cricket::ChannelManager> channel_manager_;
188 std::unique_ptr<webrtc::MediaControllerInterface> media_controller_;
189 MockWebRtcSession session_;
190 MockPeerConnection pc_;
191
192 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
193};
194
hbosc82f2e12016-09-05 01:36:50 -0700195class RTCTestStats : public RTCStats {
hbosd565b732016-08-30 14:04:35 -0700196 public:
hbosfc5e0502016-10-06 02:06:10 -0700197 WEBRTC_RTCSTATS_DECL();
198
hbosc82f2e12016-09-05 01:36:50 -0700199 RTCTestStats(const std::string& id, int64_t timestamp_us)
200 : RTCStats(id, timestamp_us),
201 dummy_stat("dummyStat") {}
202
hbosc82f2e12016-09-05 01:36:50 -0700203 RTCStatsMember<int32_t> dummy_stat;
204};
205
hbosfc5e0502016-10-06 02:06:10 -0700206WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats",
207 &dummy_stat);
hbosc82f2e12016-09-05 01:36:50 -0700208
209// Overrides the stats collection to verify thread usage and that the resulting
210// partial reports are merged.
211class FakeRTCStatsCollector : public RTCStatsCollector,
212 public RTCStatsCollectorCallback {
213 public:
214 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
215 PeerConnection* pc,
216 int64_t cache_lifetime_us) {
217 return rtc::scoped_refptr<FakeRTCStatsCollector>(
218 new rtc::RefCountedObject<FakeRTCStatsCollector>(
219 pc, cache_lifetime_us));
220 }
221
222 // RTCStatsCollectorCallback implementation.
223 void OnStatsDelivered(
224 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
225 EXPECT_TRUE(signaling_thread_->IsCurrent());
226 rtc::CritScope cs(&lock_);
227 delivered_report_ = report;
228 }
229
230 void VerifyThreadUsageAndResultsMerging() {
231 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
232 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
233 }
234
235 bool HasVerifiedResults() {
236 EXPECT_TRUE(signaling_thread_->IsCurrent());
237 rtc::CritScope cs(&lock_);
238 if (!delivered_report_)
239 return false;
240 EXPECT_EQ(produced_on_signaling_thread_, 1);
241 EXPECT_EQ(produced_on_worker_thread_, 1);
242 EXPECT_EQ(produced_on_network_thread_, 1);
243
244 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
245 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
246 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
247
248 produced_on_signaling_thread_ = 0;
249 produced_on_worker_thread_ = 0;
250 produced_on_network_thread_ = 0;
251 delivered_report_ = nullptr;
252 return true;
hbosd565b732016-08-30 14:04:35 -0700253 }
254
255 protected:
hbosc82f2e12016-09-05 01:36:50 -0700256 FakeRTCStatsCollector(
257 PeerConnection* pc,
258 int64_t cache_lifetime)
259 : RTCStatsCollector(pc, cache_lifetime),
260 signaling_thread_(pc->session()->signaling_thread()),
261 worker_thread_(pc->session()->worker_thread()),
262 network_thread_(pc->session()->network_thread()) {
263 }
264
265 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
266 EXPECT_TRUE(signaling_thread_->IsCurrent());
267 {
268 rtc::CritScope cs(&lock_);
269 EXPECT_FALSE(delivered_report_);
270 ++produced_on_signaling_thread_;
271 }
272
273 rtc::scoped_refptr<RTCStatsReport> signaling_report =
274 RTCStatsReport::Create();
275 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
276 new RTCTestStats("SignalingThreadStats", timestamp_us)));
277 AddPartialResults(signaling_report);
278 }
279 void ProducePartialResultsOnWorkerThread(int64_t timestamp_us) override {
280 EXPECT_TRUE(worker_thread_->IsCurrent());
281 {
282 rtc::CritScope cs(&lock_);
283 EXPECT_FALSE(delivered_report_);
284 ++produced_on_worker_thread_;
285 }
286
287 rtc::scoped_refptr<RTCStatsReport> worker_report = RTCStatsReport::Create();
288 worker_report->AddStats(std::unique_ptr<const RTCStats>(
289 new RTCTestStats("WorkerThreadStats", timestamp_us)));
290 AddPartialResults(worker_report);
291 }
292 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
293 EXPECT_TRUE(network_thread_->IsCurrent());
294 {
295 rtc::CritScope cs(&lock_);
296 EXPECT_FALSE(delivered_report_);
297 ++produced_on_network_thread_;
298 }
299
300 rtc::scoped_refptr<RTCStatsReport> network_report =
301 RTCStatsReport::Create();
302 network_report->AddStats(std::unique_ptr<const RTCStats>(
303 new RTCTestStats("NetworkThreadStats", timestamp_us)));
304 AddPartialResults(network_report);
305 }
306
307 private:
308 rtc::Thread* const signaling_thread_;
309 rtc::Thread* const worker_thread_;
310 rtc::Thread* const network_thread_;
311
312 rtc::CriticalSection lock_;
313 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
314 int produced_on_signaling_thread_ = 0;
315 int produced_on_worker_thread_ = 0;
316 int produced_on_network_thread_ = 0;
hbosd565b732016-08-30 14:04:35 -0700317};
318
hbosc82f2e12016-09-05 01:36:50 -0700319class StatsCallback : public RTCStatsCollectorCallback {
320 public:
321 static rtc::scoped_refptr<StatsCallback> Create(
322 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
323 return rtc::scoped_refptr<StatsCallback>(
324 new rtc::RefCountedObject<StatsCallback>(report_ptr));
325 }
326
327 void OnStatsDelivered(
328 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
329 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
330 report_ = report;
331 if (report_ptr_)
332 *report_ptr_ = report_;
333 }
334
335 rtc::scoped_refptr<const RTCStatsReport> report() const {
336 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
337 return report_;
338 }
339
340 protected:
341 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
342 : report_ptr_(report_ptr) {}
343
344 private:
345 rtc::ThreadChecker thread_checker_;
346 rtc::scoped_refptr<const RTCStatsReport> report_;
347 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
348};
349
350class RTCStatsCollectorTest : public testing::Test {
351 public:
352 RTCStatsCollectorTest()
353 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
354 collector_(RTCStatsCollector::Create(
355 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
356 }
357
358 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
359 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
360 collector_->GetStatsReport(callback);
361 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
hboscc555c52016-10-18 12:48:31 -0700362 int64_t after = rtc::TimeUTCMicros();
363 for (const RTCStats& stats : *callback->report()) {
364 EXPECT_LE(stats.timestamp_us(), after);
365 }
hbosc82f2e12016-09-05 01:36:50 -0700366 return callback->report();
367 }
368
hbosc47a0c32016-10-11 14:54:49 -0700369 const RTCIceCandidateStats* ExpectReportContainsCandidate(
hbosab9f6e42016-10-07 02:18:47 -0700370 const rtc::scoped_refptr<const RTCStatsReport>& report,
371 const cricket::Candidate& candidate,
372 bool is_local) {
hbosc47a0c32016-10-11 14:54:49 -0700373 const RTCStats* stats = report->Get("RTCIceCandidate_" + candidate.id());
hbosab9f6e42016-10-07 02:18:47 -0700374 EXPECT_TRUE(stats);
375 const RTCIceCandidateStats* candidate_stats;
376 if (is_local)
377 candidate_stats = &stats->cast_to<RTCLocalIceCandidateStats>();
378 else
379 candidate_stats = &stats->cast_to<RTCRemoteIceCandidateStats>();
380 EXPECT_EQ(*candidate_stats->ip, candidate.address().ipaddr().ToString());
381 EXPECT_EQ(*candidate_stats->port,
382 static_cast<int32_t>(candidate.address().port()));
383 EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
384 EXPECT_EQ(*candidate_stats->candidate_type,
hboscc555c52016-10-18 12:48:31 -0700385 CandidateTypeToRTCIceCandidateTypeForTesting(candidate.type()));
hbosab9f6e42016-10-07 02:18:47 -0700386 EXPECT_EQ(*candidate_stats->priority,
387 static_cast<int32_t>(candidate.priority()));
388 // TODO(hbos): Define candidate_stats->url. crbug.com/632723
389 EXPECT_FALSE(candidate_stats->url.is_defined());
hbosc47a0c32016-10-11 14:54:49 -0700390 return candidate_stats;
391 }
392
393 void ExpectReportContainsCandidatePair(
394 const rtc::scoped_refptr<const RTCStatsReport>& report,
395 const cricket::TransportStats& transport_stats) {
396 for (const auto& channel_stats : transport_stats.channel_stats) {
397 for (const cricket::ConnectionInfo& info :
398 channel_stats.connection_infos) {
399 const std::string& id = "RTCIceCandidatePair_" +
400 info.local_candidate.id() + "_" + info.remote_candidate.id();
401 const RTCStats* stats = report->Get(id);
hbos2fa7c672016-10-24 04:00:05 -0700402 ASSERT_TRUE(stats);
hbosc47a0c32016-10-11 14:54:49 -0700403 const RTCIceCandidatePairStats& candidate_pair_stats =
404 stats->cast_to<RTCIceCandidatePairStats>();
405
406 // TODO(hbos): Define all the undefined |candidate_pair_stats| stats.
407 // The EXPECT_FALSE are for the undefined stats, see also todos listed
hbos5d79a7c2016-10-24 09:27:10 -0700408 // in rtcstats_objects.h. crbug.com/633550
hbosc47a0c32016-10-11 14:54:49 -0700409 EXPECT_FALSE(candidate_pair_stats.transport_id.is_defined());
410 const RTCIceCandidateStats* local_candidate =
411 ExpectReportContainsCandidate(report, info.local_candidate, true);
412 EXPECT_EQ(*candidate_pair_stats.local_candidate_id,
413 local_candidate->id());
414 const RTCIceCandidateStats* remote_candidate =
415 ExpectReportContainsCandidate(report, info.remote_candidate, false);
416 EXPECT_EQ(*candidate_pair_stats.remote_candidate_id,
417 remote_candidate->id());
418
419 EXPECT_FALSE(candidate_pair_stats.state.is_defined());
420 EXPECT_FALSE(candidate_pair_stats.priority.is_defined());
421 EXPECT_FALSE(candidate_pair_stats.nominated.is_defined());
422 EXPECT_EQ(*candidate_pair_stats.writable, info.writable);
423 EXPECT_FALSE(candidate_pair_stats.readable.is_defined());
424 EXPECT_EQ(*candidate_pair_stats.bytes_sent,
425 static_cast<uint64_t>(info.sent_total_bytes));
426 EXPECT_EQ(*candidate_pair_stats.bytes_received,
427 static_cast<uint64_t>(info.recv_total_bytes));
428 EXPECT_FALSE(candidate_pair_stats.total_rtt.is_defined());
429 EXPECT_EQ(*candidate_pair_stats.current_rtt,
430 static_cast<double>(info.rtt) / 1000.0);
431 EXPECT_FALSE(
432 candidate_pair_stats.available_outgoing_bitrate.is_defined());
433 EXPECT_FALSE(
434 candidate_pair_stats.available_incoming_bitrate.is_defined());
435 EXPECT_FALSE(candidate_pair_stats.requests_received.is_defined());
436 EXPECT_EQ(*candidate_pair_stats.requests_sent,
437 static_cast<uint64_t>(info.sent_ping_requests_total));
438 EXPECT_EQ(*candidate_pair_stats.responses_received,
439 static_cast<uint64_t>(info.recv_ping_responses));
440 EXPECT_EQ(*candidate_pair_stats.responses_sent,
441 static_cast<uint64_t>(info.sent_ping_responses));
442 EXPECT_FALSE(
443 candidate_pair_stats.retransmissions_received.is_defined());
444 EXPECT_FALSE(candidate_pair_stats.retransmissions_sent.is_defined());
445 EXPECT_FALSE(
446 candidate_pair_stats.consent_requests_received.is_defined());
447 EXPECT_FALSE(candidate_pair_stats.consent_requests_sent.is_defined());
448 EXPECT_FALSE(
449 candidate_pair_stats.consent_responses_received.is_defined());
450 EXPECT_FALSE(candidate_pair_stats.consent_responses_sent.is_defined());
451 }
452 }
hbosab9f6e42016-10-07 02:18:47 -0700453 }
454
hbos6ab97ce2016-10-03 14:16:56 -0700455 void ExpectReportContainsCertificateInfo(
456 const rtc::scoped_refptr<const RTCStatsReport>& report,
457 const CertificateInfo& cert_info) {
458 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
459 const RTCStats* stats = report->Get(
460 "RTCCertificate_" + cert_info.fingerprints[i]);
hbos2fa7c672016-10-24 04:00:05 -0700461 ASSERT_TRUE(stats);
hbos6ab97ce2016-10-03 14:16:56 -0700462 const RTCCertificateStats& cert_stats =
463 stats->cast_to<const RTCCertificateStats>();
464 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
465 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
466 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
467 if (i + 1 < cert_info.fingerprints.size()) {
468 EXPECT_EQ(*cert_stats.issuer_certificate_id,
469 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
470 } else {
471 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
472 }
473 }
474 }
475
hbos2fa7c672016-10-24 04:00:05 -0700476 void ExpectReportContainsTransportStats(
477 const rtc::scoped_refptr<const RTCStatsReport>& report,
478 const cricket::TransportStats& transport,
479 const CertificateInfo* local_certinfo,
480 const CertificateInfo* remote_certinfo) {
481 std::string rtcp_transport_stats_id;
482 for (const auto& channel_stats : transport.channel_stats) {
483 if (channel_stats.component == cricket::ICE_CANDIDATE_COMPONENT_RTCP) {
484 rtcp_transport_stats_id = "RTCTransport_" + transport.transport_name +
485 "_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP);
486 }
487 }
488 for (const auto& channel_stats : transport.channel_stats) {
489 const cricket::ConnectionInfo* best_connection_info = nullptr;
490 const RTCStats* stats = report->Get(
491 "RTCTransport_" + transport.transport_name + "_" +
492 rtc::ToString<>(channel_stats.component));
493 ASSERT_TRUE(stats);
494 const RTCTransportStats& transport_stats =
495 stats->cast_to<const RTCTransportStats>();
496 uint64_t bytes_sent = 0;
497 uint64_t bytes_received = 0;
498 for (const cricket::ConnectionInfo& info :
499 channel_stats.connection_infos) {
500 bytes_sent += info.sent_total_bytes;
501 bytes_received += info.recv_total_bytes;
502 if (info.best_connection)
503 best_connection_info = &info;
504 }
505 EXPECT_EQ(*transport_stats.bytes_sent, bytes_sent);
506 EXPECT_EQ(*transport_stats.bytes_received, bytes_received);
507 if (best_connection_info) {
508 EXPECT_EQ(*transport_stats.active_connection, true);
509 // TODO(hbos): Instead of testing how the ID looks, test that the
510 // corresponding pair's IP addresses are equal to the IP addresses of
511 // the |best_connection_info| data. crbug.com/653873
512 EXPECT_EQ(*transport_stats.selected_candidate_pair_id,
513 "RTCIceCandidatePair_" +
514 best_connection_info->local_candidate.id() + "_" +
515 best_connection_info->remote_candidate.id());
516 EXPECT_TRUE(report->Get(*transport_stats.selected_candidate_pair_id));
517 } else {
518 EXPECT_EQ(*transport_stats.active_connection, false);
519 EXPECT_FALSE(transport_stats.selected_candidate_pair_id.is_defined());
520 }
521 if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP &&
522 !rtcp_transport_stats_id.empty()) {
523 EXPECT_EQ(*transport_stats.rtcp_transport_stats_id,
524 rtcp_transport_stats_id);
525 } else {
526 EXPECT_FALSE(transport_stats.rtcp_transport_stats_id.is_defined());
527 }
528 if (local_certinfo && remote_certinfo) {
529 EXPECT_EQ(*transport_stats.local_certificate_id,
530 "RTCCertificate_" + local_certinfo->fingerprints[0]);
531 EXPECT_EQ(*transport_stats.remote_certificate_id,
532 "RTCCertificate_" + remote_certinfo->fingerprints[0]);
533 EXPECT_TRUE(report->Get(*transport_stats.local_certificate_id));
534 EXPECT_TRUE(report->Get(*transport_stats.remote_certificate_id));
535 } else {
536 EXPECT_FALSE(transport_stats.local_certificate_id.is_defined());
537 EXPECT_FALSE(transport_stats.remote_certificate_id.is_defined());
538 }
539 }
540 }
541
hboscc555c52016-10-18 12:48:31 -0700542 void ExpectReportContainsDataChannel(
543 const rtc::scoped_refptr<const RTCStatsReport>& report,
544 const DataChannel& data_channel) {
545 const RTCStats* stats = report->Get("RTCDataChannel_" +
546 rtc::ToString<>(data_channel.id()));
547 EXPECT_TRUE(stats);
548 const RTCDataChannelStats& data_channel_stats =
549 stats->cast_to<const RTCDataChannelStats>();
550 EXPECT_EQ(*data_channel_stats.label, data_channel.label());
551 EXPECT_EQ(*data_channel_stats.protocol, data_channel.protocol());
552 EXPECT_EQ(*data_channel_stats.datachannelid, data_channel.id());
553 EXPECT_EQ(*data_channel_stats.state,
554 DataStateToRTCDataChannelStateForTesting(data_channel.state()));
555 EXPECT_EQ(*data_channel_stats.messages_sent, data_channel.messages_sent());
556 EXPECT_EQ(*data_channel_stats.bytes_sent, data_channel.bytes_sent());
557 EXPECT_EQ(*data_channel_stats.messages_received,
558 data_channel.messages_received());
559 EXPECT_EQ(*data_channel_stats.bytes_received,
560 data_channel.bytes_received());
561 }
562
hbosc82f2e12016-09-05 01:36:50 -0700563 protected:
564 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
565 rtc::scoped_refptr<RTCStatsCollector> collector_;
566};
567
568TEST_F(RTCStatsCollectorTest, SingleCallback) {
569 rtc::scoped_refptr<const RTCStatsReport> result;
570 collector_->GetStatsReport(StatsCallback::Create(&result));
571 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
572}
573
574TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
575 rtc::scoped_refptr<const RTCStatsReport> a;
576 rtc::scoped_refptr<const RTCStatsReport> b;
577 rtc::scoped_refptr<const RTCStatsReport> c;
578 collector_->GetStatsReport(StatsCallback::Create(&a));
579 collector_->GetStatsReport(StatsCallback::Create(&b));
580 collector_->GetStatsReport(StatsCallback::Create(&c));
581 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
582 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
583 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
584 EXPECT_EQ(a.get(), b.get());
585 EXPECT_EQ(b.get(), c.get());
586}
587
588TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
hbosd565b732016-08-30 14:04:35 -0700589 // Caching should ensure |a| and |b| are the same report.
hbosc82f2e12016-09-05 01:36:50 -0700590 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
591 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700592 EXPECT_EQ(a.get(), b.get());
593 // Invalidate cache by clearing it.
hbosc82f2e12016-09-05 01:36:50 -0700594 collector_->ClearCachedStatsReport();
595 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700596 EXPECT_NE(b.get(), c.get());
597 // Invalidate cache by advancing time.
hbosfdafab82016-09-14 06:02:13 -0700598 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700599 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700600 EXPECT_TRUE(d);
601 EXPECT_NE(c.get(), d.get());
602}
603
hbosc82f2e12016-09-05 01:36:50 -0700604TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
hbosc82f2e12016-09-05 01:36:50 -0700605 rtc::scoped_refptr<const RTCStatsReport> a;
606 rtc::scoped_refptr<const RTCStatsReport> b;
607 rtc::scoped_refptr<const RTCStatsReport> c;
608 collector_->GetStatsReport(StatsCallback::Create(&a));
609 collector_->GetStatsReport(StatsCallback::Create(&b));
610 // Cache is invalidated after 50 ms.
hbosfdafab82016-09-14 06:02:13 -0700611 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
hbosc82f2e12016-09-05 01:36:50 -0700612 collector_->GetStatsReport(StatsCallback::Create(&c));
613 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
614 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
615 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
616 EXPECT_EQ(a.get(), b.get());
617 // The act of doing |AdvanceTime| processes all messages. If this was not the
618 // case we might not require |c| to be fresher than |b|.
619 EXPECT_NE(c.get(), b.get());
620}
621
hbos6ab97ce2016-10-03 14:16:56 -0700622TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
623 std::unique_ptr<CertificateInfo> local_certinfo =
624 CreateFakeCertificateAndInfoFromDers(
625 std::vector<std::string>({ "(local) single certificate" }));
626 std::unique_ptr<CertificateInfo> remote_certinfo =
627 CreateFakeCertificateAndInfoFromDers(
628 std::vector<std::string>({ "(remote) single certificate" }));
629
630 // Mock the session to return the local and remote certificates.
631 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
632 [this](SessionStats* stats) {
633 stats->transport_stats["transport"].transport_name = "transport";
634 return true;
635 }));
636 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
637 Invoke([this, &local_certinfo](const std::string& transport_name,
638 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
639 if (transport_name == "transport") {
640 *certificate = local_certinfo->certificate;
641 return true;
642 }
643 return false;
644 }));
645 EXPECT_CALL(test_->session(),
646 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
647 [this, &remote_certinfo](const std::string& transport_name) {
648 if (transport_name == "transport")
649 return remote_certinfo->certificate->ssl_certificate().GetReference();
650 return static_cast<rtc::SSLCertificate*>(nullptr);
651 }));
652
653 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
654 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
655 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
656}
657
658TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
659 std::unique_ptr<CertificateInfo> audio_local_certinfo =
660 CreateFakeCertificateAndInfoFromDers(
661 std::vector<std::string>({ "(local) audio" }));
662 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
663 audio_local_certinfo->ders);
664 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
665 CreateFakeCertificateAndInfoFromDers(
666 std::vector<std::string>({ "(remote) audio" }));
667 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
668 audio_remote_certinfo->ders);
669
670 std::unique_ptr<CertificateInfo> video_local_certinfo =
671 CreateFakeCertificateAndInfoFromDers(
672 std::vector<std::string>({ "(local) video" }));
673 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
674 video_local_certinfo->ders);
675 std::unique_ptr<CertificateInfo> video_remote_certinfo =
676 CreateFakeCertificateAndInfoFromDers(
677 std::vector<std::string>({ "(remote) video" }));
678 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
679 video_remote_certinfo->ders);
680
681 // Mock the session to return the local and remote certificates.
682 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
683 [this](SessionStats* stats) {
684 stats->transport_stats["audio"].transport_name = "audio";
685 stats->transport_stats["video"].transport_name = "video";
686 return true;
687 }));
688 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
689 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
690 const std::string& transport_name,
691 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
692 if (transport_name == "audio") {
693 *certificate = audio_local_certinfo->certificate;
694 return true;
695 }
696 if (transport_name == "video") {
697 *certificate = video_local_certinfo->certificate;
698 return true;
699 }
700 return false;
701 }));
702 EXPECT_CALL(test_->session(),
703 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
704 [this, &audio_remote_certinfo, &video_remote_certinfo](
705 const std::string& transport_name) {
706 if (transport_name == "audio") {
707 return audio_remote_certinfo->certificate->ssl_certificate()
708 .GetReference();
709 }
710 if (transport_name == "video") {
711 return video_remote_certinfo->certificate->ssl_certificate()
712 .GetReference();
713 }
714 return static_cast<rtc::SSLCertificate*>(nullptr);
715 }));
716
717 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
718 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
719 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
720 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
721 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
722}
723
724TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
725 std::vector<std::string> local_ders;
726 local_ders.push_back("(local) this");
727 local_ders.push_back("(local) is");
728 local_ders.push_back("(local) a");
729 local_ders.push_back("(local) chain");
730 std::unique_ptr<CertificateInfo> local_certinfo =
731 CreateFakeCertificateAndInfoFromDers(local_ders);
732 std::vector<std::string> remote_ders;
733 remote_ders.push_back("(remote) this");
734 remote_ders.push_back("(remote) is");
735 remote_ders.push_back("(remote) another");
736 remote_ders.push_back("(remote) chain");
737 std::unique_ptr<CertificateInfo> remote_certinfo =
738 CreateFakeCertificateAndInfoFromDers(remote_ders);
739
740 // Mock the session to return the local and remote certificates.
741 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
742 [this](SessionStats* stats) {
743 stats->transport_stats["transport"].transport_name = "transport";
744 return true;
745 }));
746 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
747 Invoke([this, &local_certinfo](const std::string& transport_name,
748 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
749 if (transport_name == "transport") {
750 *certificate = local_certinfo->certificate;
751 return true;
752 }
753 return false;
754 }));
755 EXPECT_CALL(test_->session(),
756 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
757 [this, &remote_certinfo](const std::string& transport_name) {
758 if (transport_name == "transport")
759 return remote_certinfo->certificate->ssl_certificate().GetReference();
760 return static_cast<rtc::SSLCertificate*>(nullptr);
761 }));
762
763 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
764 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
765 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
766}
767
hboscc555c52016-10-18 12:48:31 -0700768TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
769 test_->data_channels().push_back(
770 new MockDataChannel(0, DataChannelInterface::kConnecting));
771 test_->data_channels().push_back(
772 new MockDataChannel(1, DataChannelInterface::kOpen));
773 test_->data_channels().push_back(
774 new MockDataChannel(2, DataChannelInterface::kClosing));
775 test_->data_channels().push_back(
776 new MockDataChannel(3, DataChannelInterface::kClosed));
777
778 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
779 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
780 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
781 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
782 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
783
784 test_->data_channels().clear();
785 test_->data_channels().push_back(
786 new MockDataChannel(0, DataChannelInterface::kConnecting,
787 1, 2, 3, 4));
788 test_->data_channels().push_back(
789 new MockDataChannel(1, DataChannelInterface::kOpen,
790 5, 6, 7, 8));
791 test_->data_channels().push_back(
792 new MockDataChannel(2, DataChannelInterface::kClosing,
793 9, 10, 11, 12));
794 test_->data_channels().push_back(
795 new MockDataChannel(3, DataChannelInterface::kClosed,
796 13, 14, 15, 16));
797
798 collector_->ClearCachedStatsReport();
799 report = GetStatsReport();
800 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
801 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
802 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
803 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
804}
805
hbosab9f6e42016-10-07 02:18:47 -0700806TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
807 // Candidates in the first transport stats.
808 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
809 "1.2.3.4", 5,
810 "a_local_host's protocol",
811 cricket::LOCAL_PORT_TYPE,
812 0);
813 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
814 "6.7.8.9", 10,
815 "remote_srflx's protocol",
816 cricket::STUN_PORT_TYPE,
817 1);
818 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
819 "11.12.13.14", 15,
820 "a_local_prflx's protocol",
821 cricket::PRFLX_PORT_TYPE,
822 2);
823 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
824 "16.17.18.19", 20,
825 "a_remote_relay's protocol",
826 cricket::RELAY_PORT_TYPE,
827 3);
828 // Candidates in the second transport stats.
829 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate(
830 "42.42.42.42", 42,
831 "b_local's protocol",
832 cricket::LOCAL_PORT_TYPE,
833 42);
834 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
835 "42.42.42.42", 42,
836 "b_remote's protocol",
837 cricket::LOCAL_PORT_TYPE,
838 42);
839
840 SessionStats session_stats;
841
842 cricket::TransportChannelStats a_transport_channel_stats;
843 a_transport_channel_stats.connection_infos.push_back(
844 cricket::ConnectionInfo());
845 a_transport_channel_stats.connection_infos[0].local_candidate =
846 *a_local_host.get();
847 a_transport_channel_stats.connection_infos[0].remote_candidate =
848 *a_remote_srflx.get();
849 a_transport_channel_stats.connection_infos.push_back(
850 cricket::ConnectionInfo());
851 a_transport_channel_stats.connection_infos[1].local_candidate =
852 *a_local_prflx.get();
853 a_transport_channel_stats.connection_infos[1].remote_candidate =
854 *a_remote_relay.get();
855 session_stats.transport_stats["a"].channel_stats.push_back(
856 a_transport_channel_stats);
857
858 cricket::TransportChannelStats b_transport_channel_stats;
859 b_transport_channel_stats.connection_infos.push_back(
860 cricket::ConnectionInfo());
861 b_transport_channel_stats.connection_infos[0].local_candidate =
862 *b_local.get();
863 b_transport_channel_stats.connection_infos[0].remote_candidate =
864 *b_remote.get();
865 session_stats.transport_stats["b"].channel_stats.push_back(
866 b_transport_channel_stats);
867
868 // Mock the session to return the desired candidates.
869 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
870 [this, &session_stats](SessionStats* stats) {
871 *stats = session_stats;
872 return true;
873 }));
874
875 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
876 ExpectReportContainsCandidate(report, *a_local_host.get(), true);
877 ExpectReportContainsCandidate(report, *a_remote_srflx.get(), false);
878 ExpectReportContainsCandidate(report, *a_local_prflx.get(), true);
879 ExpectReportContainsCandidate(report, *a_remote_relay.get(), false);
880 ExpectReportContainsCandidate(report, *b_local.get(), true);
881 ExpectReportContainsCandidate(report, *b_remote.get(), false);
882}
883
hbosc47a0c32016-10-11 14:54:49 -0700884TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
885 std::unique_ptr<cricket::Candidate> local_candidate = CreateFakeCandidate(
886 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
887 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
888 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
889
890 SessionStats session_stats;
891
892 cricket::ConnectionInfo connection_info;
893 connection_info.local_candidate = *local_candidate.get();
894 connection_info.remote_candidate = *remote_candidate.get();
895 connection_info.writable = true;
896 connection_info.sent_total_bytes = 42;
897 connection_info.recv_total_bytes = 1234;
898 connection_info.rtt = 1337;
899 connection_info.sent_ping_requests_total = 1010;
900 connection_info.recv_ping_responses = 4321;
901 connection_info.sent_ping_responses = 1000;
902
903 cricket::TransportChannelStats transport_channel_stats;
904 transport_channel_stats.connection_infos.push_back(connection_info);
905 session_stats.transport_stats["transport"].transport_name = "transport";
906 session_stats.transport_stats["transport"].channel_stats.push_back(
907 transport_channel_stats);
908
909 // Mock the session to return the desired candidates.
910 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
911 [this, &session_stats](SessionStats* stats) {
912 *stats = session_stats;
913 return true;
914 }));
915
916 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
917 ExpectReportContainsCandidatePair(
918 report, session_stats.transport_stats["transport"]);
919}
920
hbosd565b732016-08-30 14:04:35 -0700921TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
hbosc82f2e12016-09-05 01:36:50 -0700922 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700923 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
924 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
925 const RTCStats* stats = report->Get("RTCPeerConnection");
926 EXPECT_TRUE(stats);
hbosd565b732016-08-30 14:04:35 -0700927 {
928 // Expected stats with no data channels
929 const RTCPeerConnectionStats& pcstats =
930 stats->cast_to<RTCPeerConnectionStats>();
931 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(0));
932 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(0));
933 }
934
935 test_->data_channels().push_back(
hboscc555c52016-10-18 12:48:31 -0700936 new MockDataChannel(0, DataChannelInterface::kConnecting));
hbosd565b732016-08-30 14:04:35 -0700937 test_->data_channels().push_back(
hboscc555c52016-10-18 12:48:31 -0700938 new MockDataChannel(1, DataChannelInterface::kOpen));
hbosd565b732016-08-30 14:04:35 -0700939 test_->data_channels().push_back(
hboscc555c52016-10-18 12:48:31 -0700940 new MockDataChannel(2, DataChannelInterface::kClosing));
hbosd565b732016-08-30 14:04:35 -0700941 test_->data_channels().push_back(
hboscc555c52016-10-18 12:48:31 -0700942 new MockDataChannel(3, DataChannelInterface::kClosed));
hbosd565b732016-08-30 14:04:35 -0700943
hbosc82f2e12016-09-05 01:36:50 -0700944 collector_->ClearCachedStatsReport();
945 report = GetStatsReport();
hbosd565b732016-08-30 14:04:35 -0700946 EXPECT_EQ(report->GetStatsOfType<RTCPeerConnectionStats>().size(),
947 static_cast<size_t>(1)) << "Expecting 1 RTCPeerConnectionStats.";
948 stats = report->Get("RTCPeerConnection");
hbos2fa7c672016-10-24 04:00:05 -0700949 ASSERT_TRUE(stats);
hbosd565b732016-08-30 14:04:35 -0700950 {
951 // Expected stats with the above four data channels
952 // TODO(hbos): When the |RTCPeerConnectionStats| is the number of data
953 // channels that have been opened and closed, not the numbers currently
954 // open/closed, we would expect opened >= closed and (opened - closed) to be
955 // the number currently open. crbug.com/636818.
956 const RTCPeerConnectionStats& pcstats =
957 stats->cast_to<RTCPeerConnectionStats>();
958 EXPECT_EQ(*pcstats.data_channels_opened, static_cast<uint32_t>(1));
959 EXPECT_EQ(*pcstats.data_channels_closed, static_cast<uint32_t>(3));
960 }
961}
962
hbos2fa7c672016-10-24 04:00:05 -0700963TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
964 std::unique_ptr<cricket::Candidate> rtp_local_candidate = CreateFakeCandidate(
965 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
966 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
967 CreateFakeCandidate("42.42.42.42", 42, "protocol",
968 cricket::LOCAL_PORT_TYPE, 42);
969 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
970 CreateFakeCandidate("42.42.42.42", 42, "protocol",
971 cricket::LOCAL_PORT_TYPE, 42);
972 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
973 CreateFakeCandidate("42.42.42.42", 42, "protocol",
974 cricket::LOCAL_PORT_TYPE, 42);
975
976 SessionStats session_stats;
977 session_stats.transport_stats["transport"].transport_name = "transport";
978
979 cricket::ConnectionInfo rtp_connection_info;
980 rtp_connection_info.best_connection = false;
981 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
982 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
983 rtp_connection_info.sent_total_bytes = 42;
984 rtp_connection_info.recv_total_bytes = 1337;
985 cricket::TransportChannelStats rtp_transport_channel_stats;
986 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
987 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
988 session_stats.transport_stats["transport"].channel_stats.push_back(
989 rtp_transport_channel_stats);
990
991
992 // Mock the session to return the desired candidates.
993 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
994 [this, &session_stats](SessionStats* stats) {
995 *stats = session_stats;
996 return true;
997 }));
998
999 // Get stats without RTCP, an active connection or certificates.
1000 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1001 ExpectReportContainsTransportStats(
1002 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1003
1004 cricket::ConnectionInfo rtcp_connection_info;
1005 rtcp_connection_info.best_connection = false;
1006 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
1007 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
1008 rtcp_connection_info.sent_total_bytes = 1337;
1009 rtcp_connection_info.recv_total_bytes = 42;
1010 cricket::TransportChannelStats rtcp_transport_channel_stats;
1011 rtcp_transport_channel_stats.component =
1012 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
1013 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
1014 session_stats.transport_stats["transport"].channel_stats.push_back(
1015 rtcp_transport_channel_stats);
1016
1017 collector_->ClearCachedStatsReport();
1018 // Get stats with RTCP and without an active connection or certificates.
1019 report = GetStatsReport();
1020 ExpectReportContainsTransportStats(
1021 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1022
1023 // Get stats with an active connection.
1024 rtcp_connection_info.best_connection = true;
1025
1026 collector_->ClearCachedStatsReport();
1027 report = GetStatsReport();
1028 ExpectReportContainsTransportStats(
1029 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1030
1031 // Get stats with certificates.
1032 std::unique_ptr<CertificateInfo> local_certinfo =
1033 CreateFakeCertificateAndInfoFromDers(
1034 std::vector<std::string>({ "(local) local", "(local) chain" }));
1035 std::unique_ptr<CertificateInfo> remote_certinfo =
1036 CreateFakeCertificateAndInfoFromDers(
1037 std::vector<std::string>({ "(remote) local", "(remote) chain" }));
1038 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
1039 Invoke([this, &local_certinfo](const std::string& transport_name,
1040 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
1041 if (transport_name == "transport") {
1042 *certificate = local_certinfo->certificate;
1043 return true;
1044 }
1045 return false;
1046 }));
1047 EXPECT_CALL(test_->session(),
1048 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
1049 [this, &remote_certinfo](const std::string& transport_name) {
1050 if (transport_name == "transport")
1051 return remote_certinfo->certificate->ssl_certificate().GetReference();
1052 return static_cast<rtc::SSLCertificate*>(nullptr);
1053 }));
1054
1055 collector_->ClearCachedStatsReport();
1056 report = GetStatsReport();
1057 ExpectReportContainsTransportStats(
1058 report, session_stats.transport_stats["transport"],
1059 local_certinfo.get(), remote_certinfo.get());
1060}
1061
hbosc82f2e12016-09-05 01:36:50 -07001062class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
1063 public:
1064 RTCStatsCollectorTestWithFakeCollector()
1065 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
1066 collector_(FakeRTCStatsCollector::Create(
1067 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
1068 }
1069
1070 protected:
1071 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
1072 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
1073};
1074
1075TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
1076 collector_->VerifyThreadUsageAndResultsMerging();
1077}
1078
1079} // namespace
1080
hbosd565b732016-08-30 14:04:35 -07001081} // namespace webrtc