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