Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: webrtc/api/rtcstatscollector_unittest.cc

Issue 2514883002: Create //webrtc/api:libjingle_peerconnection_api + refactorings. (Closed)
Patch Set: Big move! Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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
11 #include "webrtc/api/rtcstatscollector.h"
12
13 #include <memory>
14 #include <ostream>
15 #include <string>
16 #include <vector>
17
18 #include "webrtc/api/mediastream.h"
19 #include "webrtc/api/mediastreamtrack.h"
20 #include "webrtc/api/jsepsessiondescription.h"
21 #include "webrtc/api/stats/rtcstats_objects.h"
22 #include "webrtc/api/stats/rtcstatsreport.h"
23 #include "webrtc/api/test/mock_datachannel.h"
24 #include "webrtc/api/test/mock_peerconnection.h"
25 #include "webrtc/api/test/mock_webrtcsession.h"
26 #include "webrtc/base/checks.h"
27 #include "webrtc/base/fakeclock.h"
28 #include "webrtc/base/fakesslidentity.h"
29 #include "webrtc/base/gunit.h"
30 #include "webrtc/base/logging.h"
31 #include "webrtc/base/socketaddress.h"
32 #include "webrtc/base/thread_checker.h"
33 #include "webrtc/base/timedelta.h"
34 #include "webrtc/base/timeutils.h"
35 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
36 #include "webrtc/media/base/fakemediaengine.h"
37 #include "webrtc/media/base/test/mock_mediachannel.h"
38 #include "webrtc/p2p/base/p2pconstants.h"
39 #include "webrtc/p2p/base/port.h"
40
41 using testing::_;
42 using testing::Invoke;
43 using testing::Return;
44 using testing::ReturnNull;
45 using testing::ReturnRef;
46 using testing::SetArgPointee;
47
48 namespace webrtc {
49
50 // These are used by gtest code, such as if |EXPECT_EQ| fails.
51 void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) {
52 *os << stats.ToString();
53 }
54
55 void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) {
56 *os << stats.ToString();
57 }
58
59 void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) {
60 *os << stats.ToString();
61 }
62
63 void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) {
64 *os << stats.ToString();
65 }
66
67 void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) {
68 *os << stats.ToString();
69 }
70
71 void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) {
72 *os << stats.ToString();
73 }
74
75 void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) {
76 *os << stats.ToString();
77 }
78
79 void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) {
80 *os << stats.ToString();
81 }
82
83 void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) {
84 *os << stats.ToString();
85 }
86
87 void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) {
88 *os << stats.ToString();
89 }
90
91 void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) {
92 *os << stats.ToString();
93 }
94
95 namespace {
96
97 const int64_t kGetStatsReportTimeoutMs = 1000;
98
99 struct CertificateInfo {
100 rtc::scoped_refptr<rtc::RTCCertificate> certificate;
101 std::vector<std::string> ders;
102 std::vector<std::string> pems;
103 std::vector<std::string> fingerprints;
104 };
105
106 std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers(
107 const std::vector<std::string>& ders) {
108 RTC_CHECK(!ders.empty());
109 std::unique_ptr<CertificateInfo> info(new CertificateInfo());
110 info->ders = ders;
111 for (const std::string& der : ders) {
112 info->pems.push_back(rtc::SSLIdentity::DerToPem(
113 "CERTIFICATE",
114 reinterpret_cast<const unsigned char*>(der.c_str()),
115 der.length()));
116 }
117 info->certificate =
118 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>(
119 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems))));
120 // Strip header/footer and newline characters of PEM strings.
121 for (size_t i = 0; i < info->pems.size(); ++i) {
122 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27,
123 "", 0, &info->pems[i]);
124 rtc::replace_substrs("-----END CERTIFICATE-----", 25,
125 "", 0, &info->pems[i]);
126 rtc::replace_substrs("\n", 1,
127 "", 0, &info->pems[i]);
128 }
129 // Fingerprint of leaf certificate.
130 std::unique_ptr<rtc::SSLFingerprint> fp(
131 rtc::SSLFingerprint::Create("sha-1",
132 &info->certificate->ssl_certificate()));
133 EXPECT_TRUE(fp);
134 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
135 // Fingerprints of the rest of the chain.
136 std::unique_ptr<rtc::SSLCertChain> chain =
137 info->certificate->ssl_certificate().GetChain();
138 if (chain) {
139 for (size_t i = 0; i < chain->GetSize(); i++) {
140 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i)));
141 EXPECT_TRUE(fp);
142 info->fingerprints.push_back(fp->GetRfc4572Fingerprint());
143 }
144 }
145 EXPECT_EQ(info->ders.size(), info->fingerprints.size());
146 return info;
147 }
148
149 std::unique_ptr<cricket::Candidate> CreateFakeCandidate(
150 const std::string& hostname,
151 int port,
152 const std::string& protocol,
153 const std::string& candidate_type,
154 uint32_t priority) {
155 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate());
156 candidate->set_address(rtc::SocketAddress(hostname, port));
157 candidate->set_protocol(protocol);
158 candidate->set_type(candidate_type);
159 candidate->set_priority(priority);
160 return candidate;
161 }
162
163 class FakeAudioProcessorForStats
164 : public rtc::RefCountedObject<AudioProcessorInterface> {
165 public:
166 FakeAudioProcessorForStats(
167 AudioProcessorInterface::AudioProcessorStats stats)
168 : stats_(stats) {
169 }
170
171 void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override {
172 *stats = stats_;
173 }
174
175 private:
176 AudioProcessorInterface::AudioProcessorStats stats_;
177 };
178
179 class FakeAudioTrackForStats
180 : public MediaStreamTrack<AudioTrackInterface> {
181 public:
182 static rtc::scoped_refptr<FakeAudioTrackForStats> Create(
183 const std::string& id,
184 MediaStreamTrackInterface::TrackState state,
185 int signal_level,
186 rtc::scoped_refptr<FakeAudioProcessorForStats> processor) {
187 rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats(
188 new rtc::RefCountedObject<FakeAudioTrackForStats>(
189 id, signal_level, processor));
190 audio_track_stats->set_state(state);
191 return audio_track_stats;
192 }
193
194 FakeAudioTrackForStats(
195 const std::string& id,
196 int signal_level,
197 rtc::scoped_refptr<FakeAudioProcessorForStats> processor)
198 : MediaStreamTrack<AudioTrackInterface>(id),
199 signal_level_(signal_level),
200 processor_(processor) {
201 }
202
203 std::string kind() const override {
204 return MediaStreamTrackInterface::kAudioKind;
205 }
206 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; }
207 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
208 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
209 bool GetSignalLevel(int* level) override {
210 *level = signal_level_;
211 return true;
212 }
213 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
214 return processor_;
215 }
216
217 private:
218 int signal_level_;
219 rtc::scoped_refptr<FakeAudioProcessorForStats> processor_;
220 };
221
222 class FakeVideoTrackSourceForStats
223 : public rtc::RefCountedObject<VideoTrackSourceInterface> {
224 public:
225 FakeVideoTrackSourceForStats(VideoTrackSourceInterface::Stats stats)
226 : stats_(stats) {
227 }
228
229 MediaSourceInterface::SourceState state() const override {
230 return MediaSourceInterface::kLive;
231 }
232 bool remote() const override { return false; }
233 void RegisterObserver(ObserverInterface* observer) override {}
234 void UnregisterObserver(ObserverInterface* observer) override {}
235 void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink,
236 const rtc::VideoSinkWants& wants) override {}
237 void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override {
238 }
239 bool is_screencast() const override { return false; }
240 rtc::Optional<bool> needs_denoising() const override {
241 return rtc::Optional<bool>();
242 }
243 bool GetStats(VideoTrackSourceInterface::Stats* stats) override {
244 *stats = stats_;
245 return true;
246 }
247
248 private:
249 VideoTrackSourceInterface::Stats stats_;
250 };
251
252 class FakeVideoTrackForStats
253 : public MediaStreamTrack<VideoTrackInterface> {
254 public:
255 static rtc::scoped_refptr<FakeVideoTrackForStats> Create(
256 const std::string& id,
257 MediaStreamTrackInterface::TrackState state,
258 rtc::scoped_refptr<VideoTrackSourceInterface> source) {
259 rtc::scoped_refptr<FakeVideoTrackForStats> video_track(
260 new rtc::RefCountedObject<FakeVideoTrackForStats>(id, source));
261 video_track->set_state(state);
262 return video_track;
263 }
264
265 FakeVideoTrackForStats(
266 const std::string& id,
267 rtc::scoped_refptr<VideoTrackSourceInterface> source)
268 : MediaStreamTrack<VideoTrackInterface>(id),
269 source_(source) {
270 }
271
272 std::string kind() const override {
273 return MediaStreamTrackInterface::kVideoKind;
274 }
275 VideoTrackSourceInterface* GetSource() const override {
276 return source_;
277 }
278
279 private:
280 rtc::scoped_refptr<VideoTrackSourceInterface> source_;
281 };
282
283 class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver {
284 public:
285 RTCStatsCollectorTestHelper()
286 : worker_thread_(rtc::Thread::Current()),
287 network_thread_(rtc::Thread::Current()),
288 media_engine_(new cricket::FakeMediaEngine()),
289 channel_manager_(
290 new cricket::ChannelManager(media_engine_,
291 worker_thread_,
292 network_thread_)),
293 media_controller_(
294 MediaControllerInterface::Create(cricket::MediaConfig(),
295 worker_thread_,
296 channel_manager_.get(),
297 &event_log_)),
298 session_(media_controller_.get()),
299 pc_() {
300 // Default return values for mocks.
301 EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr));
302 EXPECT_CALL(pc_, remote_streams()).WillRepeatedly(Return(nullptr));
303 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_));
304 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly(
305 ReturnRef(data_channels_));
306 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
307 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
308 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false));
309 EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly(
310 Return(false));
311 EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_))
312 .WillRepeatedly(Return(nullptr));
313 }
314
315 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; }
316 rtc::Thread* worker_thread() { return worker_thread_; }
317 rtc::Thread* network_thread() { return network_thread_; }
318 cricket::FakeMediaEngine* media_engine() { return media_engine_; }
319 MockWebRtcSession& session() { return session_; }
320 MockPeerConnection& pc() { return pc_; }
321 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() {
322 return data_channels_;
323 }
324
325 // SetSessionDescriptionObserver overrides.
326 void OnSuccess() override {}
327 void OnFailure(const std::string& error) override {
328 RTC_NOTREACHED() << error;
329 }
330
331 private:
332 rtc::ScopedFakeClock fake_clock_;
333 RtcEventLogNullImpl event_log_;
334 rtc::Thread* const worker_thread_;
335 rtc::Thread* const network_thread_;
336 cricket::FakeMediaEngine* media_engine_;
337 std::unique_ptr<cricket::ChannelManager> channel_manager_;
338 std::unique_ptr<MediaControllerInterface> media_controller_;
339 MockWebRtcSession session_;
340 MockPeerConnection pc_;
341
342 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
343 };
344
345 class RTCTestStats : public RTCStats {
346 public:
347 WEBRTC_RTCSTATS_DECL();
348
349 RTCTestStats(const std::string& id, int64_t timestamp_us)
350 : RTCStats(id, timestamp_us),
351 dummy_stat("dummyStat") {}
352
353 RTCStatsMember<int32_t> dummy_stat;
354 };
355
356 WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats",
357 &dummy_stat);
358
359 // Overrides the stats collection to verify thread usage and that the resulting
360 // partial reports are merged.
361 class FakeRTCStatsCollector : public RTCStatsCollector,
362 public RTCStatsCollectorCallback {
363 public:
364 static rtc::scoped_refptr<FakeRTCStatsCollector> Create(
365 PeerConnection* pc,
366 int64_t cache_lifetime_us) {
367 return rtc::scoped_refptr<FakeRTCStatsCollector>(
368 new rtc::RefCountedObject<FakeRTCStatsCollector>(
369 pc, cache_lifetime_us));
370 }
371
372 // RTCStatsCollectorCallback implementation.
373 void OnStatsDelivered(
374 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
375 EXPECT_TRUE(signaling_thread_->IsCurrent());
376 rtc::CritScope cs(&lock_);
377 delivered_report_ = report;
378 }
379
380 void VerifyThreadUsageAndResultsMerging() {
381 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this));
382 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs);
383 }
384
385 bool HasVerifiedResults() {
386 EXPECT_TRUE(signaling_thread_->IsCurrent());
387 rtc::CritScope cs(&lock_);
388 if (!delivered_report_)
389 return false;
390 EXPECT_EQ(produced_on_signaling_thread_, 1);
391 EXPECT_EQ(produced_on_worker_thread_, 1);
392 EXPECT_EQ(produced_on_network_thread_, 1);
393
394 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats"));
395 EXPECT_TRUE(delivered_report_->Get("WorkerThreadStats"));
396 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats"));
397
398 produced_on_signaling_thread_ = 0;
399 produced_on_worker_thread_ = 0;
400 produced_on_network_thread_ = 0;
401 delivered_report_ = nullptr;
402 return true;
403 }
404
405 protected:
406 FakeRTCStatsCollector(
407 PeerConnection* pc,
408 int64_t cache_lifetime)
409 : RTCStatsCollector(pc, cache_lifetime),
410 signaling_thread_(pc->session()->signaling_thread()),
411 worker_thread_(pc->session()->worker_thread()),
412 network_thread_(pc->session()->network_thread()) {
413 }
414
415 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override {
416 EXPECT_TRUE(signaling_thread_->IsCurrent());
417 {
418 rtc::CritScope cs(&lock_);
419 EXPECT_FALSE(delivered_report_);
420 ++produced_on_signaling_thread_;
421 }
422
423 rtc::scoped_refptr<RTCStatsReport> signaling_report =
424 RTCStatsReport::Create(0);
425 signaling_report->AddStats(std::unique_ptr<const RTCStats>(
426 new RTCTestStats("SignalingThreadStats", timestamp_us)));
427 AddPartialResults(signaling_report);
428 }
429 void ProducePartialResultsOnWorkerThread(int64_t timestamp_us) override {
430 EXPECT_TRUE(worker_thread_->IsCurrent());
431 {
432 rtc::CritScope cs(&lock_);
433 EXPECT_FALSE(delivered_report_);
434 ++produced_on_worker_thread_;
435 }
436
437 rtc::scoped_refptr<RTCStatsReport> worker_report =
438 RTCStatsReport::Create(0);
439 worker_report->AddStats(std::unique_ptr<const RTCStats>(
440 new RTCTestStats("WorkerThreadStats", timestamp_us)));
441 AddPartialResults(worker_report);
442 }
443 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override {
444 EXPECT_TRUE(network_thread_->IsCurrent());
445 {
446 rtc::CritScope cs(&lock_);
447 EXPECT_FALSE(delivered_report_);
448 ++produced_on_network_thread_;
449 }
450
451 rtc::scoped_refptr<RTCStatsReport> network_report =
452 RTCStatsReport::Create(0);
453 network_report->AddStats(std::unique_ptr<const RTCStats>(
454 new RTCTestStats("NetworkThreadStats", timestamp_us)));
455 AddPartialResults(network_report);
456 }
457
458 private:
459 rtc::Thread* const signaling_thread_;
460 rtc::Thread* const worker_thread_;
461 rtc::Thread* const network_thread_;
462
463 rtc::CriticalSection lock_;
464 rtc::scoped_refptr<const RTCStatsReport> delivered_report_;
465 int produced_on_signaling_thread_ = 0;
466 int produced_on_worker_thread_ = 0;
467 int produced_on_network_thread_ = 0;
468 };
469
470 class StatsCallback : public RTCStatsCollectorCallback {
471 public:
472 static rtc::scoped_refptr<StatsCallback> Create(
473 rtc::scoped_refptr<const RTCStatsReport>* report_ptr = nullptr) {
474 return rtc::scoped_refptr<StatsCallback>(
475 new rtc::RefCountedObject<StatsCallback>(report_ptr));
476 }
477
478 void OnStatsDelivered(
479 const rtc::scoped_refptr<const RTCStatsReport>& report) override {
480 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
481 report_ = report;
482 if (report_ptr_)
483 *report_ptr_ = report_;
484 }
485
486 rtc::scoped_refptr<const RTCStatsReport> report() const {
487 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
488 return report_;
489 }
490
491 protected:
492 explicit StatsCallback(rtc::scoped_refptr<const RTCStatsReport>* report_ptr)
493 : report_ptr_(report_ptr) {}
494
495 private:
496 rtc::ThreadChecker thread_checker_;
497 rtc::scoped_refptr<const RTCStatsReport> report_;
498 rtc::scoped_refptr<const RTCStatsReport>* report_ptr_;
499 };
500
501 class RTCStatsCollectorTest : public testing::Test {
502 public:
503 RTCStatsCollectorTest()
504 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
505 collector_(RTCStatsCollector::Create(
506 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
507 }
508
509 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() {
510 rtc::scoped_refptr<StatsCallback> callback = StatsCallback::Create();
511 collector_->GetStatsReport(callback);
512 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs);
513 int64_t after = rtc::TimeUTCMicros();
514 for (const RTCStats& stats : *callback->report()) {
515 EXPECT_LE(stats.timestamp_us(), after);
516 }
517 return callback->report();
518 }
519
520 const RTCIceCandidateStats* ExpectReportContainsCandidate(
521 const rtc::scoped_refptr<const RTCStatsReport>& report,
522 const cricket::Candidate& candidate,
523 bool is_local) {
524 const RTCStats* stats = report->Get("RTCIceCandidate_" + candidate.id());
525 EXPECT_TRUE(stats);
526 const RTCIceCandidateStats* candidate_stats;
527 if (is_local)
528 candidate_stats = &stats->cast_to<RTCLocalIceCandidateStats>();
529 else
530 candidate_stats = &stats->cast_to<RTCRemoteIceCandidateStats>();
531 EXPECT_EQ(*candidate_stats->ip, candidate.address().ipaddr().ToString());
532 EXPECT_EQ(*candidate_stats->port,
533 static_cast<int32_t>(candidate.address().port()));
534 EXPECT_EQ(*candidate_stats->protocol, candidate.protocol());
535 EXPECT_EQ(*candidate_stats->candidate_type,
536 CandidateTypeToRTCIceCandidateTypeForTesting(candidate.type()));
537 EXPECT_EQ(*candidate_stats->priority,
538 static_cast<int32_t>(candidate.priority()));
539 // TODO(hbos): Define candidate_stats->url. crbug.com/632723
540 EXPECT_FALSE(candidate_stats->url.is_defined());
541 return candidate_stats;
542 }
543
544 void ExpectReportContainsCandidatePair(
545 const rtc::scoped_refptr<const RTCStatsReport>& report,
546 const cricket::TransportStats& transport_stats) {
547 for (const auto& channel_stats : transport_stats.channel_stats) {
548 for (const cricket::ConnectionInfo& info :
549 channel_stats.connection_infos) {
550 const std::string& id = "RTCIceCandidatePair_" +
551 info.local_candidate.id() + "_" + info.remote_candidate.id();
552 const RTCStats* stats = report->Get(id);
553 ASSERT_TRUE(stats);
554 const RTCIceCandidatePairStats& candidate_pair_stats =
555 stats->cast_to<RTCIceCandidatePairStats>();
556
557 // TODO(hbos): Define all the undefined |candidate_pair_stats| stats.
558 // The EXPECT_FALSE are for the undefined stats, see also todos listed
559 // in rtcstats_objects.h. crbug.com/633550
560 EXPECT_FALSE(candidate_pair_stats.transport_id.is_defined());
561 const RTCIceCandidateStats* local_candidate =
562 ExpectReportContainsCandidate(report, info.local_candidate, true);
563 EXPECT_EQ(*candidate_pair_stats.local_candidate_id,
564 local_candidate->id());
565 const RTCIceCandidateStats* remote_candidate =
566 ExpectReportContainsCandidate(report, info.remote_candidate, false);
567 EXPECT_EQ(*candidate_pair_stats.remote_candidate_id,
568 remote_candidate->id());
569
570 EXPECT_FALSE(candidate_pair_stats.state.is_defined());
571 EXPECT_FALSE(candidate_pair_stats.priority.is_defined());
572 EXPECT_FALSE(candidate_pair_stats.nominated.is_defined());
573 EXPECT_EQ(*candidate_pair_stats.writable, info.writable);
574 EXPECT_FALSE(candidate_pair_stats.readable.is_defined());
575 EXPECT_EQ(*candidate_pair_stats.bytes_sent,
576 static_cast<uint64_t>(info.sent_total_bytes));
577 EXPECT_EQ(*candidate_pair_stats.bytes_received,
578 static_cast<uint64_t>(info.recv_total_bytes));
579 EXPECT_FALSE(candidate_pair_stats.total_rtt.is_defined());
580 EXPECT_EQ(*candidate_pair_stats.current_rtt,
581 static_cast<double>(info.rtt) / 1000.0);
582 EXPECT_FALSE(
583 candidate_pair_stats.available_outgoing_bitrate.is_defined());
584 EXPECT_FALSE(
585 candidate_pair_stats.available_incoming_bitrate.is_defined());
586 EXPECT_FALSE(candidate_pair_stats.requests_received.is_defined());
587 EXPECT_EQ(*candidate_pair_stats.requests_sent,
588 static_cast<uint64_t>(info.sent_ping_requests_total));
589 EXPECT_EQ(*candidate_pair_stats.responses_received,
590 static_cast<uint64_t>(info.recv_ping_responses));
591 EXPECT_EQ(*candidate_pair_stats.responses_sent,
592 static_cast<uint64_t>(info.sent_ping_responses));
593 EXPECT_FALSE(
594 candidate_pair_stats.retransmissions_received.is_defined());
595 EXPECT_FALSE(candidate_pair_stats.retransmissions_sent.is_defined());
596 EXPECT_FALSE(
597 candidate_pair_stats.consent_requests_received.is_defined());
598 EXPECT_FALSE(candidate_pair_stats.consent_requests_sent.is_defined());
599 EXPECT_FALSE(
600 candidate_pair_stats.consent_responses_received.is_defined());
601 EXPECT_FALSE(candidate_pair_stats.consent_responses_sent.is_defined());
602 }
603 }
604 }
605
606 void ExpectReportContainsCertificateInfo(
607 const rtc::scoped_refptr<const RTCStatsReport>& report,
608 const CertificateInfo& cert_info) {
609 for (size_t i = 0; i < cert_info.fingerprints.size(); ++i) {
610 const RTCStats* stats = report->Get(
611 "RTCCertificate_" + cert_info.fingerprints[i]);
612 ASSERT_TRUE(stats);
613 const RTCCertificateStats& cert_stats =
614 stats->cast_to<const RTCCertificateStats>();
615 EXPECT_EQ(*cert_stats.fingerprint, cert_info.fingerprints[i]);
616 EXPECT_EQ(*cert_stats.fingerprint_algorithm, "sha-1");
617 EXPECT_EQ(*cert_stats.base64_certificate, cert_info.pems[i]);
618 if (i + 1 < cert_info.fingerprints.size()) {
619 EXPECT_EQ(*cert_stats.issuer_certificate_id,
620 "RTCCertificate_" + cert_info.fingerprints[i + 1]);
621 } else {
622 EXPECT_FALSE(cert_stats.issuer_certificate_id.is_defined());
623 }
624 }
625 }
626
627 void ExpectReportContainsTransportStats(
628 const rtc::scoped_refptr<const RTCStatsReport>& report,
629 const cricket::TransportStats& transport,
630 const CertificateInfo* local_certinfo,
631 const CertificateInfo* remote_certinfo) {
632 std::string rtcp_transport_stats_id;
633 for (const auto& channel_stats : transport.channel_stats) {
634 if (channel_stats.component == cricket::ICE_CANDIDATE_COMPONENT_RTCP) {
635 rtcp_transport_stats_id = "RTCTransport_" + transport.transport_name +
636 "_" + rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP);
637 }
638 }
639 for (const auto& channel_stats : transport.channel_stats) {
640 const cricket::ConnectionInfo* best_connection_info = nullptr;
641 const RTCStats* stats = report->Get(
642 "RTCTransport_" + transport.transport_name + "_" +
643 rtc::ToString<>(channel_stats.component));
644 ASSERT_TRUE(stats);
645 const RTCTransportStats& transport_stats =
646 stats->cast_to<const RTCTransportStats>();
647 uint64_t bytes_sent = 0;
648 uint64_t bytes_received = 0;
649 for (const cricket::ConnectionInfo& info :
650 channel_stats.connection_infos) {
651 bytes_sent += info.sent_total_bytes;
652 bytes_received += info.recv_total_bytes;
653 if (info.best_connection)
654 best_connection_info = &info;
655 }
656 EXPECT_EQ(*transport_stats.bytes_sent, bytes_sent);
657 EXPECT_EQ(*transport_stats.bytes_received, bytes_received);
658 if (best_connection_info) {
659 EXPECT_EQ(*transport_stats.active_connection, true);
660 // TODO(hbos): Instead of testing how the ID looks, test that the
661 // corresponding pair's IP addresses are equal to the IP addresses of
662 // the |best_connection_info| data. crbug.com/653873
663 EXPECT_EQ(*transport_stats.selected_candidate_pair_id,
664 "RTCIceCandidatePair_" +
665 best_connection_info->local_candidate.id() + "_" +
666 best_connection_info->remote_candidate.id());
667 EXPECT_TRUE(report->Get(*transport_stats.selected_candidate_pair_id));
668 } else {
669 EXPECT_EQ(*transport_stats.active_connection, false);
670 EXPECT_FALSE(transport_stats.selected_candidate_pair_id.is_defined());
671 }
672 if (channel_stats.component != cricket::ICE_CANDIDATE_COMPONENT_RTCP &&
673 !rtcp_transport_stats_id.empty()) {
674 EXPECT_EQ(*transport_stats.rtcp_transport_stats_id,
675 rtcp_transport_stats_id);
676 } else {
677 EXPECT_FALSE(transport_stats.rtcp_transport_stats_id.is_defined());
678 }
679 if (local_certinfo && remote_certinfo) {
680 EXPECT_EQ(*transport_stats.local_certificate_id,
681 "RTCCertificate_" + local_certinfo->fingerprints[0]);
682 EXPECT_EQ(*transport_stats.remote_certificate_id,
683 "RTCCertificate_" + remote_certinfo->fingerprints[0]);
684 EXPECT_TRUE(report->Get(*transport_stats.local_certificate_id));
685 EXPECT_TRUE(report->Get(*transport_stats.remote_certificate_id));
686 } else {
687 EXPECT_FALSE(transport_stats.local_certificate_id.is_defined());
688 EXPECT_FALSE(transport_stats.remote_certificate_id.is_defined());
689 }
690 }
691 }
692
693 void ExpectReportContainsDataChannel(
694 const rtc::scoped_refptr<const RTCStatsReport>& report,
695 const DataChannel& data_channel) {
696 const RTCStats* stats = report->Get("RTCDataChannel_" +
697 rtc::ToString<>(data_channel.id()));
698 EXPECT_TRUE(stats);
699 const RTCDataChannelStats& data_channel_stats =
700 stats->cast_to<const RTCDataChannelStats>();
701 EXPECT_EQ(*data_channel_stats.label, data_channel.label());
702 EXPECT_EQ(*data_channel_stats.protocol, data_channel.protocol());
703 EXPECT_EQ(*data_channel_stats.datachannelid, data_channel.id());
704 EXPECT_EQ(*data_channel_stats.state,
705 DataStateToRTCDataChannelStateForTesting(data_channel.state()));
706 EXPECT_EQ(*data_channel_stats.messages_sent, data_channel.messages_sent());
707 EXPECT_EQ(*data_channel_stats.bytes_sent, data_channel.bytes_sent());
708 EXPECT_EQ(*data_channel_stats.messages_received,
709 data_channel.messages_received());
710 EXPECT_EQ(*data_channel_stats.bytes_received,
711 data_channel.bytes_received());
712 }
713
714 protected:
715 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
716 rtc::scoped_refptr<RTCStatsCollector> collector_;
717 };
718
719 TEST_F(RTCStatsCollectorTest, SingleCallback) {
720 rtc::scoped_refptr<const RTCStatsReport> result;
721 collector_->GetStatsReport(StatsCallback::Create(&result));
722 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs);
723 }
724
725 TEST_F(RTCStatsCollectorTest, MultipleCallbacks) {
726 rtc::scoped_refptr<const RTCStatsReport> a;
727 rtc::scoped_refptr<const RTCStatsReport> b;
728 rtc::scoped_refptr<const RTCStatsReport> c;
729 collector_->GetStatsReport(StatsCallback::Create(&a));
730 collector_->GetStatsReport(StatsCallback::Create(&b));
731 collector_->GetStatsReport(StatsCallback::Create(&c));
732 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
733 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
734 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
735 EXPECT_EQ(a.get(), b.get());
736 EXPECT_EQ(b.get(), c.get());
737 }
738
739 TEST_F(RTCStatsCollectorTest, CachedStatsReports) {
740 // Caching should ensure |a| and |b| are the same report.
741 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport();
742 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport();
743 EXPECT_EQ(a.get(), b.get());
744 // Invalidate cache by clearing it.
745 collector_->ClearCachedStatsReport();
746 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport();
747 EXPECT_NE(b.get(), c.get());
748 // Invalidate cache by advancing time.
749 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
750 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport();
751 EXPECT_TRUE(d);
752 EXPECT_NE(c.get(), d.get());
753 }
754
755 TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) {
756 rtc::scoped_refptr<const RTCStatsReport> a;
757 rtc::scoped_refptr<const RTCStatsReport> b;
758 rtc::scoped_refptr<const RTCStatsReport> c;
759 collector_->GetStatsReport(StatsCallback::Create(&a));
760 collector_->GetStatsReport(StatsCallback::Create(&b));
761 // Cache is invalidated after 50 ms.
762 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51));
763 collector_->GetStatsReport(StatsCallback::Create(&c));
764 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs);
765 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs);
766 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs);
767 EXPECT_EQ(a.get(), b.get());
768 // The act of doing |AdvanceTime| processes all messages. If this was not the
769 // case we might not require |c| to be fresher than |b|.
770 EXPECT_NE(c.get(), b.get());
771 }
772
773 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) {
774 std::unique_ptr<CertificateInfo> local_certinfo =
775 CreateFakeCertificateAndInfoFromDers(
776 std::vector<std::string>({ "(local) single certificate" }));
777 std::unique_ptr<CertificateInfo> remote_certinfo =
778 CreateFakeCertificateAndInfoFromDers(
779 std::vector<std::string>({ "(remote) single certificate" }));
780
781 // Mock the session to return the local and remote certificates.
782 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
783 [this](SessionStats* stats) {
784 stats->transport_stats["transport"].transport_name = "transport";
785 return true;
786 }));
787 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
788 Invoke([this, &local_certinfo](const std::string& transport_name,
789 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
790 if (transport_name == "transport") {
791 *certificate = local_certinfo->certificate;
792 return true;
793 }
794 return false;
795 }));
796 EXPECT_CALL(test_->session(),
797 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
798 [this, &remote_certinfo](const std::string& transport_name) {
799 if (transport_name == "transport")
800 return remote_certinfo->certificate->ssl_certificate().GetReference();
801 return static_cast<rtc::SSLCertificate*>(nullptr);
802 }));
803
804 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
805 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
806 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
807 }
808
809 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) {
810 std::unique_ptr<CertificateInfo> audio_local_certinfo =
811 CreateFakeCertificateAndInfoFromDers(
812 std::vector<std::string>({ "(local) audio" }));
813 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers(
814 audio_local_certinfo->ders);
815 std::unique_ptr<CertificateInfo> audio_remote_certinfo =
816 CreateFakeCertificateAndInfoFromDers(
817 std::vector<std::string>({ "(remote) audio" }));
818 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
819 audio_remote_certinfo->ders);
820
821 std::unique_ptr<CertificateInfo> video_local_certinfo =
822 CreateFakeCertificateAndInfoFromDers(
823 std::vector<std::string>({ "(local) video" }));
824 video_local_certinfo = CreateFakeCertificateAndInfoFromDers(
825 video_local_certinfo->ders);
826 std::unique_ptr<CertificateInfo> video_remote_certinfo =
827 CreateFakeCertificateAndInfoFromDers(
828 std::vector<std::string>({ "(remote) video" }));
829 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers(
830 video_remote_certinfo->ders);
831
832 // Mock the session to return the local and remote certificates.
833 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
834 [this](SessionStats* stats) {
835 stats->transport_stats["audio"].transport_name = "audio";
836 stats->transport_stats["video"].transport_name = "video";
837 return true;
838 }));
839 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
840 Invoke([this, &audio_local_certinfo, &video_local_certinfo](
841 const std::string& transport_name,
842 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
843 if (transport_name == "audio") {
844 *certificate = audio_local_certinfo->certificate;
845 return true;
846 }
847 if (transport_name == "video") {
848 *certificate = video_local_certinfo->certificate;
849 return true;
850 }
851 return false;
852 }));
853 EXPECT_CALL(test_->session(),
854 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
855 [this, &audio_remote_certinfo, &video_remote_certinfo](
856 const std::string& transport_name) {
857 if (transport_name == "audio") {
858 return audio_remote_certinfo->certificate->ssl_certificate()
859 .GetReference();
860 }
861 if (transport_name == "video") {
862 return video_remote_certinfo->certificate->ssl_certificate()
863 .GetReference();
864 }
865 return static_cast<rtc::SSLCertificate*>(nullptr);
866 }));
867
868 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
869 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo.get());
870 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo.get());
871 ExpectReportContainsCertificateInfo(report, *video_local_certinfo.get());
872 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo.get());
873 }
874
875 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) {
876 std::vector<std::string> local_ders;
877 local_ders.push_back("(local) this");
878 local_ders.push_back("(local) is");
879 local_ders.push_back("(local) a");
880 local_ders.push_back("(local) chain");
881 std::unique_ptr<CertificateInfo> local_certinfo =
882 CreateFakeCertificateAndInfoFromDers(local_ders);
883 std::vector<std::string> remote_ders;
884 remote_ders.push_back("(remote) this");
885 remote_ders.push_back("(remote) is");
886 remote_ders.push_back("(remote) another");
887 remote_ders.push_back("(remote) chain");
888 std::unique_ptr<CertificateInfo> remote_certinfo =
889 CreateFakeCertificateAndInfoFromDers(remote_ders);
890
891 // Mock the session to return the local and remote certificates.
892 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
893 [this](SessionStats* stats) {
894 stats->transport_stats["transport"].transport_name = "transport";
895 return true;
896 }));
897 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
898 Invoke([this, &local_certinfo](const std::string& transport_name,
899 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
900 if (transport_name == "transport") {
901 *certificate = local_certinfo->certificate;
902 return true;
903 }
904 return false;
905 }));
906 EXPECT_CALL(test_->session(),
907 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
908 [this, &remote_certinfo](const std::string& transport_name) {
909 if (transport_name == "transport")
910 return remote_certinfo->certificate->ssl_certificate().GetReference();
911 return static_cast<rtc::SSLCertificate*>(nullptr);
912 }));
913
914 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
915 ExpectReportContainsCertificateInfo(report, *local_certinfo.get());
916 ExpectReportContainsCertificateInfo(report, *remote_certinfo.get());
917 }
918
919 TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) {
920 test_->data_channels().push_back(
921 new MockDataChannel(0, DataChannelInterface::kConnecting));
922 test_->data_channels().push_back(
923 new MockDataChannel(1, DataChannelInterface::kOpen));
924 test_->data_channels().push_back(
925 new MockDataChannel(2, DataChannelInterface::kClosing));
926 test_->data_channels().push_back(
927 new MockDataChannel(3, DataChannelInterface::kClosed));
928
929 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
930 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
931 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
932 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
933 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
934
935 test_->data_channels().clear();
936 test_->data_channels().push_back(
937 new MockDataChannel(0, DataChannelInterface::kConnecting,
938 1, 2, 3, 4));
939 test_->data_channels().push_back(
940 new MockDataChannel(1, DataChannelInterface::kOpen,
941 5, 6, 7, 8));
942 test_->data_channels().push_back(
943 new MockDataChannel(2, DataChannelInterface::kClosing,
944 9, 10, 11, 12));
945 test_->data_channels().push_back(
946 new MockDataChannel(3, DataChannelInterface::kClosed,
947 13, 14, 15, 16));
948
949 collector_->ClearCachedStatsReport();
950 report = GetStatsReport();
951 ExpectReportContainsDataChannel(report, *test_->data_channels()[0]);
952 ExpectReportContainsDataChannel(report, *test_->data_channels()[1]);
953 ExpectReportContainsDataChannel(report, *test_->data_channels()[2]);
954 ExpectReportContainsDataChannel(report, *test_->data_channels()[3]);
955 }
956
957 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) {
958 // Candidates in the first transport stats.
959 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate(
960 "1.2.3.4", 5,
961 "a_local_host's protocol",
962 cricket::LOCAL_PORT_TYPE,
963 0);
964 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate(
965 "6.7.8.9", 10,
966 "remote_srflx's protocol",
967 cricket::STUN_PORT_TYPE,
968 1);
969 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate(
970 "11.12.13.14", 15,
971 "a_local_prflx's protocol",
972 cricket::PRFLX_PORT_TYPE,
973 2);
974 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate(
975 "16.17.18.19", 20,
976 "a_remote_relay's protocol",
977 cricket::RELAY_PORT_TYPE,
978 3);
979 // Candidates in the second transport stats.
980 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate(
981 "42.42.42.42", 42,
982 "b_local's protocol",
983 cricket::LOCAL_PORT_TYPE,
984 42);
985 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate(
986 "42.42.42.42", 42,
987 "b_remote's protocol",
988 cricket::LOCAL_PORT_TYPE,
989 42);
990
991 SessionStats session_stats;
992
993 cricket::TransportChannelStats a_transport_channel_stats;
994 a_transport_channel_stats.connection_infos.push_back(
995 cricket::ConnectionInfo());
996 a_transport_channel_stats.connection_infos[0].local_candidate =
997 *a_local_host.get();
998 a_transport_channel_stats.connection_infos[0].remote_candidate =
999 *a_remote_srflx.get();
1000 a_transport_channel_stats.connection_infos.push_back(
1001 cricket::ConnectionInfo());
1002 a_transport_channel_stats.connection_infos[1].local_candidate =
1003 *a_local_prflx.get();
1004 a_transport_channel_stats.connection_infos[1].remote_candidate =
1005 *a_remote_relay.get();
1006 session_stats.transport_stats["a"].channel_stats.push_back(
1007 a_transport_channel_stats);
1008
1009 cricket::TransportChannelStats b_transport_channel_stats;
1010 b_transport_channel_stats.connection_infos.push_back(
1011 cricket::ConnectionInfo());
1012 b_transport_channel_stats.connection_infos[0].local_candidate =
1013 *b_local.get();
1014 b_transport_channel_stats.connection_infos[0].remote_candidate =
1015 *b_remote.get();
1016 session_stats.transport_stats["b"].channel_stats.push_back(
1017 b_transport_channel_stats);
1018
1019 // Mock the session to return the desired candidates.
1020 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1021 [this, &session_stats](SessionStats* stats) {
1022 *stats = session_stats;
1023 return true;
1024 }));
1025
1026 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1027 ExpectReportContainsCandidate(report, *a_local_host.get(), true);
1028 ExpectReportContainsCandidate(report, *a_remote_srflx.get(), false);
1029 ExpectReportContainsCandidate(report, *a_local_prflx.get(), true);
1030 ExpectReportContainsCandidate(report, *a_remote_relay.get(), false);
1031 ExpectReportContainsCandidate(report, *b_local.get(), true);
1032 ExpectReportContainsCandidate(report, *b_remote.get(), false);
1033 }
1034
1035 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) {
1036 std::unique_ptr<cricket::Candidate> local_candidate = CreateFakeCandidate(
1037 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1038 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate(
1039 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1040
1041 SessionStats session_stats;
1042
1043 cricket::ConnectionInfo connection_info;
1044 connection_info.local_candidate = *local_candidate.get();
1045 connection_info.remote_candidate = *remote_candidate.get();
1046 connection_info.writable = true;
1047 connection_info.sent_total_bytes = 42;
1048 connection_info.recv_total_bytes = 1234;
1049 connection_info.rtt = 1337;
1050 connection_info.sent_ping_requests_total = 1010;
1051 connection_info.recv_ping_responses = 4321;
1052 connection_info.sent_ping_responses = 1000;
1053
1054 cricket::TransportChannelStats transport_channel_stats;
1055 transport_channel_stats.connection_infos.push_back(connection_info);
1056 session_stats.transport_stats["transport"].transport_name = "transport";
1057 session_stats.transport_stats["transport"].channel_stats.push_back(
1058 transport_channel_stats);
1059
1060 // Mock the session to return the desired candidates.
1061 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1062 [this, &session_stats](SessionStats* stats) {
1063 *stats = session_stats;
1064 return true;
1065 }));
1066
1067 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1068 ExpectReportContainsCandidatePair(
1069 report, session_stats.transport_stats["transport"]);
1070 }
1071
1072 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) {
1073 {
1074 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1075 RTCPeerConnectionStats expected("RTCPeerConnection",
1076 report->timestamp_us());
1077 expected.data_channels_opened = 0;
1078 expected.data_channels_closed = 0;
1079 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1080 EXPECT_EQ(expected,
1081 report->Get("RTCPeerConnection")->cast_to<
1082 RTCPeerConnectionStats>());
1083 }
1084
1085 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create(
1086 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit());
1087 test_->pc().SignalDataChannelCreated(dummy_channel_a.get());
1088 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create(
1089 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit());
1090 test_->pc().SignalDataChannelCreated(dummy_channel_b.get());
1091
1092 dummy_channel_a->SignalOpened(dummy_channel_a.get());
1093 // Closing a channel that is not opened should not affect the counts.
1094 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1095
1096 {
1097 collector_->ClearCachedStatsReport();
1098 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1099 RTCPeerConnectionStats expected("RTCPeerConnection",
1100 report->timestamp_us());
1101 expected.data_channels_opened = 1;
1102 expected.data_channels_closed = 0;
1103 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1104 EXPECT_EQ(expected,
1105 report->Get("RTCPeerConnection")->cast_to<
1106 RTCPeerConnectionStats>());
1107 }
1108
1109 dummy_channel_b->SignalOpened(dummy_channel_b.get());
1110 dummy_channel_b->SignalClosed(dummy_channel_b.get());
1111
1112 {
1113 collector_->ClearCachedStatsReport();
1114 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1115 RTCPeerConnectionStats expected("RTCPeerConnection",
1116 report->timestamp_us());
1117 expected.data_channels_opened = 2;
1118 expected.data_channels_closed = 1;
1119 EXPECT_TRUE(report->Get("RTCPeerConnection"));
1120 EXPECT_EQ(expected,
1121 report->Get("RTCPeerConnection")->cast_to<
1122 RTCPeerConnectionStats>());
1123 }
1124 }
1125
1126 TEST_F(RTCStatsCollectorTest,
1127 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) {
1128 rtc::scoped_refptr<StreamCollection> local_streams =
1129 StreamCollection::Create();
1130 rtc::scoped_refptr<StreamCollection> remote_streams =
1131 StreamCollection::Create();
1132 EXPECT_CALL(test_->pc(), local_streams())
1133 .WillRepeatedly(Return(local_streams));
1134 EXPECT_CALL(test_->pc(), remote_streams())
1135 .WillRepeatedly(Return(remote_streams));
1136
1137 rtc::scoped_refptr<MediaStream> local_stream =
1138 MediaStream::Create("LocalStreamLabel");
1139 local_streams->AddStream(local_stream);
1140 rtc::scoped_refptr<MediaStream> remote_stream =
1141 MediaStream::Create("RemoteStreamLabel");
1142 remote_streams->AddStream(remote_stream);
1143
1144 // Local audio track
1145 AudioProcessorInterface::AudioProcessorStats local_audio_processor_stats;
1146 local_audio_processor_stats.echo_return_loss = 42;
1147 local_audio_processor_stats.echo_return_loss_enhancement = 52;
1148 rtc::scoped_refptr<FakeAudioTrackForStats> local_audio_track =
1149 FakeAudioTrackForStats::Create(
1150 "LocalAudioTrackID",
1151 MediaStreamTrackInterface::TrackState::kEnded,
1152 32767,
1153 new FakeAudioProcessorForStats(local_audio_processor_stats));
1154 local_stream->AddTrack(local_audio_track);
1155
1156 // Remote audio track
1157 AudioProcessorInterface::AudioProcessorStats remote_audio_processor_stats;
1158 remote_audio_processor_stats.echo_return_loss = 13;
1159 remote_audio_processor_stats.echo_return_loss_enhancement = 37;
1160 rtc::scoped_refptr<FakeAudioTrackForStats> remote_audio_track =
1161 FakeAudioTrackForStats::Create(
1162 "RemoteAudioTrackID",
1163 MediaStreamTrackInterface::TrackState::kLive,
1164 0,
1165 new FakeAudioProcessorForStats(remote_audio_processor_stats));
1166 remote_stream->AddTrack(remote_audio_track);
1167
1168 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1169
1170 RTCMediaStreamStats expected_local_stream(
1171 "RTCMediaStream_LocalStreamLabel", report->timestamp_us());
1172 expected_local_stream.stream_identifier = local_stream->label();
1173 expected_local_stream.track_ids = std::vector<std::string>();
1174 expected_local_stream.track_ids->push_back(
1175 "RTCMediaStreamTrack_LocalAudioTrackID");
1176 EXPECT_TRUE(report->Get(expected_local_stream.id()));
1177 EXPECT_EQ(expected_local_stream,
1178 report->Get(expected_local_stream.id())->cast_to<
1179 RTCMediaStreamStats>());
1180
1181 RTCMediaStreamStats expected_remote_stream(
1182 "RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
1183 expected_remote_stream.stream_identifier = remote_stream->label();
1184 expected_remote_stream.track_ids = std::vector<std::string>();
1185 expected_remote_stream.track_ids->push_back(
1186 "RTCMediaStreamTrack_RemoteAudioTrackID");
1187 EXPECT_TRUE(report->Get(expected_remote_stream.id()));
1188 EXPECT_EQ(expected_remote_stream,
1189 report->Get(expected_remote_stream.id())->cast_to<
1190 RTCMediaStreamStats>());
1191
1192 RTCMediaStreamTrackStats expected_local_audio_track(
1193 "RTCMediaStreamTrack_LocalAudioTrackID", report->timestamp_us());
1194 expected_local_audio_track.track_identifier = local_audio_track->id();
1195 expected_local_audio_track.remote_source = false;
1196 expected_local_audio_track.ended = true;
1197 expected_local_audio_track.detached = false;
1198 expected_local_audio_track.audio_level = 1.0;
1199 expected_local_audio_track.echo_return_loss = 42.0;
1200 expected_local_audio_track.echo_return_loss_enhancement = 52.0;
1201 EXPECT_TRUE(report->Get(expected_local_audio_track.id()));
1202 EXPECT_EQ(expected_local_audio_track,
1203 report->Get(expected_local_audio_track.id())->cast_to<
1204 RTCMediaStreamTrackStats>());
1205
1206 RTCMediaStreamTrackStats expected_remote_audio_track(
1207 "RTCMediaStreamTrack_RemoteAudioTrackID", report->timestamp_us());
1208 expected_remote_audio_track.track_identifier = remote_audio_track->id();
1209 expected_remote_audio_track.remote_source = true;
1210 expected_remote_audio_track.ended = false;
1211 expected_remote_audio_track.detached = false;
1212 expected_remote_audio_track.audio_level = 0.0;
1213 expected_remote_audio_track.echo_return_loss = 13.0;
1214 expected_remote_audio_track.echo_return_loss_enhancement = 37.0;
1215 EXPECT_TRUE(report->Get(expected_remote_audio_track.id()));
1216 EXPECT_EQ(expected_remote_audio_track,
1217 report->Get(expected_remote_audio_track.id())->cast_to<
1218 RTCMediaStreamTrackStats>());
1219 }
1220
1221 TEST_F(RTCStatsCollectorTest,
1222 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) {
1223 rtc::scoped_refptr<StreamCollection> local_streams =
1224 StreamCollection::Create();
1225 rtc::scoped_refptr<StreamCollection> remote_streams =
1226 StreamCollection::Create();
1227 EXPECT_CALL(test_->pc(), local_streams())
1228 .WillRepeatedly(Return(local_streams));
1229 EXPECT_CALL(test_->pc(), remote_streams())
1230 .WillRepeatedly(Return(remote_streams));
1231
1232 rtc::scoped_refptr<MediaStream> local_stream =
1233 MediaStream::Create("LocalStreamLabel");
1234 local_streams->AddStream(local_stream);
1235 rtc::scoped_refptr<MediaStream> remote_stream =
1236 MediaStream::Create("RemoteStreamLabel");
1237 remote_streams->AddStream(remote_stream);
1238
1239 // Local video track
1240 VideoTrackSourceInterface::Stats local_video_track_source_stats;
1241 local_video_track_source_stats.input_width = 1234;
1242 local_video_track_source_stats.input_height = 4321;
1243 rtc::scoped_refptr<FakeVideoTrackSourceForStats> local_video_track_source =
1244 new FakeVideoTrackSourceForStats(local_video_track_source_stats);
1245 rtc::scoped_refptr<FakeVideoTrackForStats> local_video_track =
1246 FakeVideoTrackForStats::Create(
1247 "LocalVideoTrackID",
1248 MediaStreamTrackInterface::TrackState::kLive,
1249 local_video_track_source);
1250 local_stream->AddTrack(local_video_track);
1251
1252 // Remote video track
1253 VideoTrackSourceInterface::Stats remote_video_track_source_stats;
1254 remote_video_track_source_stats.input_width = 1234;
1255 remote_video_track_source_stats.input_height = 4321;
1256 rtc::scoped_refptr<FakeVideoTrackSourceForStats> remote_video_track_source =
1257 new FakeVideoTrackSourceForStats(remote_video_track_source_stats);
1258 rtc::scoped_refptr<FakeVideoTrackForStats> remote_video_track =
1259 FakeVideoTrackForStats::Create(
1260 "RemoteVideoTrackID",
1261 MediaStreamTrackInterface::TrackState::kEnded,
1262 remote_video_track_source);
1263 remote_stream->AddTrack(remote_video_track);
1264
1265 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1266
1267 RTCMediaStreamStats expected_local_stream(
1268 "RTCMediaStream_LocalStreamLabel", report->timestamp_us());
1269 expected_local_stream.stream_identifier = local_stream->label();
1270 expected_local_stream.track_ids = std::vector<std::string>();
1271 expected_local_stream.track_ids->push_back(
1272 "RTCMediaStreamTrack_LocalVideoTrackID");
1273 EXPECT_TRUE(report->Get(expected_local_stream.id()));
1274 EXPECT_EQ(expected_local_stream,
1275 report->Get(expected_local_stream.id())->cast_to<
1276 RTCMediaStreamStats>());
1277
1278 RTCMediaStreamStats expected_remote_stream(
1279 "RTCMediaStream_RemoteStreamLabel", report->timestamp_us());
1280 expected_remote_stream.stream_identifier = remote_stream->label();
1281 expected_remote_stream.track_ids = std::vector<std::string>();
1282 expected_remote_stream.track_ids->push_back(
1283 "RTCMediaStreamTrack_RemoteVideoTrackID");
1284 EXPECT_TRUE(report->Get(expected_remote_stream.id()));
1285 EXPECT_EQ(expected_remote_stream,
1286 report->Get(expected_remote_stream.id())->cast_to<
1287 RTCMediaStreamStats>());
1288
1289 RTCMediaStreamTrackStats expected_local_video_track(
1290 "RTCMediaStreamTrack_LocalVideoTrackID", report->timestamp_us());
1291 expected_local_video_track.track_identifier = local_video_track->id();
1292 expected_local_video_track.remote_source = false;
1293 expected_local_video_track.ended = false;
1294 expected_local_video_track.detached = false;
1295 expected_local_video_track.frame_width = 1234;
1296 expected_local_video_track.frame_height = 4321;
1297 EXPECT_TRUE(report->Get(expected_local_video_track.id()));
1298 EXPECT_EQ(expected_local_video_track,
1299 report->Get(expected_local_video_track.id())->cast_to<
1300 RTCMediaStreamTrackStats>());
1301
1302 RTCMediaStreamTrackStats expected_remote_video_track(
1303 "RTCMediaStreamTrack_RemoteVideoTrackID", report->timestamp_us());
1304 expected_remote_video_track.track_identifier = remote_video_track->id();
1305 expected_remote_video_track.remote_source = true;
1306 expected_remote_video_track.ended = true;
1307 expected_remote_video_track.detached = false;
1308 expected_remote_video_track.frame_width = 1234;
1309 expected_remote_video_track.frame_height = 4321;
1310 EXPECT_TRUE(report->Get(expected_remote_video_track.id()));
1311 EXPECT_EQ(expected_remote_video_track,
1312 report->Get(expected_remote_video_track.id())->cast_to<
1313 RTCMediaStreamTrackStats>());
1314 }
1315
1316 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
1317 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
1318 cricket::VoiceChannel voice_channel(
1319 test_->worker_thread(), test_->network_thread(), test_->media_engine(),
1320 voice_media_channel, nullptr, "VoiceContentName", false);
1321
1322 cricket::VoiceMediaInfo voice_media_info;
1323 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo());
1324 voice_media_info.receivers[0].local_stats.push_back(
1325 cricket::SsrcReceiverInfo());
1326 voice_media_info.receivers[0].local_stats[0].ssrc = 1;
1327 voice_media_info.receivers[0].packets_rcvd = 2;
1328 voice_media_info.receivers[0].bytes_rcvd = 3;
1329 voice_media_info.receivers[0].jitter_ms = 4500;
1330 voice_media_info.receivers[0].fraction_lost = 5.5f;
1331 EXPECT_CALL(*voice_media_channel, GetStats(_))
1332 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
1333
1334 SessionStats session_stats;
1335 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
1336 session_stats.transport_stats["TransportName"].transport_name =
1337 "TransportName";
1338
1339 // Make sure the associated |RTCTransportStats| is created.
1340 cricket::TransportChannelStats channel_stats;
1341 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1342 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1343 channel_stats);
1344
1345 EXPECT_CALL(test_->session(), GetTransportStats(_))
1346 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1347 EXPECT_CALL(test_->session(), voice_channel())
1348 .WillRepeatedly(Return(&voice_channel));
1349
1350 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1351
1352 RTCInboundRTPStreamStats expected_audio(
1353 "RTCInboundRTPAudioStream_1", report->timestamp_us());
1354 expected_audio.ssrc = "1";
1355 expected_audio.is_remote = false;
1356 expected_audio.media_type = "audio";
1357 expected_audio.transport_id = "RTCTransport_TransportName_" +
1358 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1359 expected_audio.packets_received = 2;
1360 expected_audio.bytes_received = 3;
1361 expected_audio.jitter = 4.5;
1362 expected_audio.fraction_lost = 5.5;
1363
1364 ASSERT(report->Get(expected_audio.id()));
1365 const RTCInboundRTPStreamStats& audio = report->Get(
1366 expected_audio.id())->cast_to<RTCInboundRTPStreamStats>();
1367 EXPECT_EQ(audio, expected_audio);
1368
1369 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1370 }
1371
1372 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
1373 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
1374 cricket::VideoChannel video_channel(
1375 test_->worker_thread(), test_->network_thread(), video_media_channel,
1376 nullptr, "VideoContentName", false);
1377
1378 cricket::VideoMediaInfo video_media_info;
1379 video_media_info.receivers.push_back(cricket::VideoReceiverInfo());
1380 video_media_info.receivers[0].local_stats.push_back(
1381 cricket::SsrcReceiverInfo());
1382 video_media_info.receivers[0].local_stats[0].ssrc = 1;
1383 video_media_info.receivers[0].packets_rcvd = 2;
1384 video_media_info.receivers[0].bytes_rcvd = 3;
1385 video_media_info.receivers[0].fraction_lost = 4.5f;
1386 EXPECT_CALL(*video_media_channel, GetStats(_))
1387 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
1388
1389 SessionStats session_stats;
1390 session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
1391 session_stats.transport_stats["TransportName"].transport_name =
1392 "TransportName";
1393
1394 // Make sure the associated |RTCTransportStats| is created.
1395 cricket::TransportChannelStats channel_stats;
1396 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1397 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1398 channel_stats);
1399
1400 EXPECT_CALL(test_->session(), GetTransportStats(_))
1401 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1402 EXPECT_CALL(test_->session(), video_channel())
1403 .WillRepeatedly(Return(&video_channel));
1404
1405 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1406
1407 RTCInboundRTPStreamStats expected_audio(
1408 "RTCInboundRTPVideoStream_1", report->timestamp_us());
1409 expected_audio.ssrc = "1";
1410 expected_audio.is_remote = false;
1411 expected_audio.media_type = "video";
1412 expected_audio.transport_id = "RTCTransport_TransportName_" +
1413 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1414 expected_audio.packets_received = 2;
1415 expected_audio.bytes_received = 3;
1416 expected_audio.fraction_lost = 4.5;
1417
1418 ASSERT(report->Get(expected_audio.id()));
1419 const RTCInboundRTPStreamStats& audio = report->Get(
1420 expected_audio.id())->cast_to<RTCInboundRTPStreamStats>();
1421 EXPECT_EQ(audio, expected_audio);
1422
1423 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1424 }
1425
1426 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
1427 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
1428 cricket::VoiceChannel voice_channel(
1429 test_->worker_thread(), test_->network_thread(), test_->media_engine(),
1430 voice_media_channel, nullptr, "VoiceContentName", false);
1431
1432 cricket::VoiceMediaInfo voice_media_info;
1433 voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
1434 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1435 voice_media_info.senders[0].local_stats[0].ssrc = 1;
1436 voice_media_info.senders[0].packets_sent = 2;
1437 voice_media_info.senders[0].bytes_sent = 3;
1438 voice_media_info.senders[0].rtt_ms = 4500;
1439 EXPECT_CALL(*voice_media_channel, GetStats(_))
1440 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true)));
1441
1442 SessionStats session_stats;
1443 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName";
1444 session_stats.transport_stats["TransportName"].transport_name =
1445 "TransportName";
1446
1447 // Make sure the associated |RTCTransportStats| is created.
1448 cricket::TransportChannelStats channel_stats;
1449 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1450 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1451 channel_stats);
1452
1453 EXPECT_CALL(test_->session(), GetTransportStats(_))
1454 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1455 EXPECT_CALL(test_->session(), voice_channel())
1456 .WillRepeatedly(Return(&voice_channel));
1457
1458 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1459
1460 RTCOutboundRTPStreamStats expected_audio(
1461 "RTCOutboundRTPAudioStream_1", report->timestamp_us());
1462 expected_audio.ssrc = "1";
1463 expected_audio.is_remote = false;
1464 expected_audio.media_type = "audio";
1465 expected_audio.transport_id = "RTCTransport_TransportName_" +
1466 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1467 expected_audio.packets_sent = 2;
1468 expected_audio.bytes_sent = 3;
1469 expected_audio.round_trip_time = 4.5;
1470
1471 ASSERT(report->Get(expected_audio.id()));
1472 const RTCOutboundRTPStreamStats& audio = report->Get(
1473 expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>();
1474 EXPECT_EQ(audio, expected_audio);
1475
1476 EXPECT_TRUE(report->Get(*expected_audio.transport_id));
1477 }
1478
1479 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
1480 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
1481 cricket::VideoChannel video_channel(
1482 test_->worker_thread(), test_->network_thread(), video_media_channel,
1483 nullptr, "VideoContentName", false);
1484
1485 cricket::VideoMediaInfo video_media_info;
1486 video_media_info.senders.push_back(cricket::VideoSenderInfo());
1487 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo());
1488 video_media_info.senders[0].local_stats[0].ssrc = 1;
1489 video_media_info.senders[0].firs_rcvd = 2;
1490 video_media_info.senders[0].plis_rcvd = 3;
1491 video_media_info.senders[0].nacks_rcvd = 4;
1492 video_media_info.senders[0].packets_sent = 5;
1493 video_media_info.senders[0].bytes_sent = 6;
1494 video_media_info.senders[0].rtt_ms = 7500;
1495 EXPECT_CALL(*video_media_channel, GetStats(_))
1496 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true)));
1497
1498 SessionStats session_stats;
1499 session_stats.proxy_to_transport["VideoContentName"] = "TransportName";
1500 session_stats.transport_stats["TransportName"].transport_name =
1501 "TransportName";
1502
1503 // Make sure the associated |RTCTransportStats| is created.
1504 cricket::TransportChannelStats channel_stats;
1505 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1506 session_stats.transport_stats["TransportName"].channel_stats.push_back(
1507 channel_stats);
1508
1509 EXPECT_CALL(test_->session(), GetTransportStats(_))
1510 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats), Return(true)));
1511 EXPECT_CALL(test_->session(), video_channel())
1512 .WillRepeatedly(Return(&video_channel));
1513
1514 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1515
1516 RTCOutboundRTPStreamStats expected_video(
1517 "RTCOutboundRTPVideoStream_1", report->timestamp_us());
1518 expected_video.ssrc = "1";
1519 expected_video.is_remote = false;
1520 expected_video.media_type = "video";
1521 expected_video.transport_id = "RTCTransport_TransportName_" +
1522 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
1523 expected_video.fir_count = 2;
1524 expected_video.pli_count = 3;
1525 expected_video.nack_count = 4;
1526 expected_video.packets_sent = 5;
1527 expected_video.bytes_sent = 6;
1528 expected_video.round_trip_time = 7.5;
1529
1530 ASSERT(report->Get(expected_video.id()));
1531 const RTCOutboundRTPStreamStats& video = report->Get(
1532 expected_video.id())->cast_to<RTCOutboundRTPStreamStats>();
1533 EXPECT_EQ(video, expected_video);
1534
1535 EXPECT_TRUE(report->Get(*expected_video.transport_id));
1536 }
1537
1538 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) {
1539 std::unique_ptr<cricket::Candidate> rtp_local_candidate = CreateFakeCandidate(
1540 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42);
1541 std::unique_ptr<cricket::Candidate> rtp_remote_candidate =
1542 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1543 cricket::LOCAL_PORT_TYPE, 42);
1544 std::unique_ptr<cricket::Candidate> rtcp_local_candidate =
1545 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1546 cricket::LOCAL_PORT_TYPE, 42);
1547 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate =
1548 CreateFakeCandidate("42.42.42.42", 42, "protocol",
1549 cricket::LOCAL_PORT_TYPE, 42);
1550
1551 SessionStats session_stats;
1552 session_stats.transport_stats["transport"].transport_name = "transport";
1553
1554 cricket::ConnectionInfo rtp_connection_info;
1555 rtp_connection_info.best_connection = false;
1556 rtp_connection_info.local_candidate = *rtp_local_candidate.get();
1557 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get();
1558 rtp_connection_info.sent_total_bytes = 42;
1559 rtp_connection_info.recv_total_bytes = 1337;
1560 cricket::TransportChannelStats rtp_transport_channel_stats;
1561 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP;
1562 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info);
1563 session_stats.transport_stats["transport"].channel_stats.push_back(
1564 rtp_transport_channel_stats);
1565
1566
1567 // Mock the session to return the desired candidates.
1568 EXPECT_CALL(test_->session(), GetTransportStats(_)).WillRepeatedly(Invoke(
1569 [this, &session_stats](SessionStats* stats) {
1570 *stats = session_stats;
1571 return true;
1572 }));
1573
1574 // Get stats without RTCP, an active connection or certificates.
1575 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
1576 ExpectReportContainsTransportStats(
1577 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1578
1579 cricket::ConnectionInfo rtcp_connection_info;
1580 rtcp_connection_info.best_connection = false;
1581 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get();
1582 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get();
1583 rtcp_connection_info.sent_total_bytes = 1337;
1584 rtcp_connection_info.recv_total_bytes = 42;
1585 cricket::TransportChannelStats rtcp_transport_channel_stats;
1586 rtcp_transport_channel_stats.component =
1587 cricket::ICE_CANDIDATE_COMPONENT_RTCP;
1588 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info);
1589 session_stats.transport_stats["transport"].channel_stats.push_back(
1590 rtcp_transport_channel_stats);
1591
1592 collector_->ClearCachedStatsReport();
1593 // Get stats with RTCP and without an active connection or certificates.
1594 report = GetStatsReport();
1595 ExpectReportContainsTransportStats(
1596 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1597
1598 // Get stats with an active connection.
1599 rtcp_connection_info.best_connection = true;
1600
1601 collector_->ClearCachedStatsReport();
1602 report = GetStatsReport();
1603 ExpectReportContainsTransportStats(
1604 report, session_stats.transport_stats["transport"], nullptr, nullptr);
1605
1606 // Get stats with certificates.
1607 std::unique_ptr<CertificateInfo> local_certinfo =
1608 CreateFakeCertificateAndInfoFromDers(
1609 std::vector<std::string>({ "(local) local", "(local) chain" }));
1610 std::unique_ptr<CertificateInfo> remote_certinfo =
1611 CreateFakeCertificateAndInfoFromDers(
1612 std::vector<std::string>({ "(remote) local", "(remote) chain" }));
1613 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly(
1614 Invoke([this, &local_certinfo](const std::string& transport_name,
1615 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
1616 if (transport_name == "transport") {
1617 *certificate = local_certinfo->certificate;
1618 return true;
1619 }
1620 return false;
1621 }));
1622 EXPECT_CALL(test_->session(),
1623 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke(
1624 [this, &remote_certinfo](const std::string& transport_name) {
1625 if (transport_name == "transport")
1626 return remote_certinfo->certificate->ssl_certificate().GetReference();
1627 return static_cast<rtc::SSLCertificate*>(nullptr);
1628 }));
1629
1630 collector_->ClearCachedStatsReport();
1631 report = GetStatsReport();
1632 ExpectReportContainsTransportStats(
1633 report, session_stats.transport_stats["transport"],
1634 local_certinfo.get(), remote_certinfo.get());
1635 }
1636
1637 class RTCStatsCollectorTestWithFakeCollector : public testing::Test {
1638 public:
1639 RTCStatsCollectorTestWithFakeCollector()
1640 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()),
1641 collector_(FakeRTCStatsCollector::Create(
1642 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) {
1643 }
1644
1645 protected:
1646 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_;
1647 rtc::scoped_refptr<FakeRTCStatsCollector> collector_;
1648 };
1649
1650 TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) {
1651 collector_->VerifyThreadUsageAndResultsMerging();
1652 }
1653
1654 } // namespace
1655
1656 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698