1 /*
2 * Copyright 2014 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 "pc/legacy_stats_collector.h"
12
13 #include <stdio.h>
14
15 #include <cstdint>
16
17 #include "absl/algorithm/container.h"
18 #include "absl/types/optional.h"
19 #include "api/audio_codecs/audio_encoder.h"
20 #include "api/candidate.h"
21 #include "api/data_channel_interface.h"
22 #include "api/media_stream_track.h"
23 #include "api/media_types.h"
24 #include "api/rtp_sender_interface.h"
25 #include "api/scoped_refptr.h"
26 #include "call/call.h"
27 #include "media/base/media_channel.h"
28 #include "modules/audio_processing/include/audio_processing_statistics.h"
29 #include "p2p/base/ice_transport_internal.h"
30 #include "pc/media_stream.h"
31 #include "pc/rtp_receiver.h"
32 #include "pc/rtp_sender.h"
33 #include "pc/sctp_data_channel.h"
34 #include "pc/test/fake_peer_connection_for_stats.h"
35 #include "pc/test/fake_video_track_source.h"
36 #include "pc/test/mock_rtp_receiver_internal.h"
37 #include "pc/test/mock_rtp_sender_internal.h"
38 #include "pc/transport_stats.h"
39 #include "pc/video_track.h"
40 #include "rtc_base/fake_ssl_identity.h"
41 #include "rtc_base/message_digest.h"
42 #include "rtc_base/net_helper.h"
43 #include "rtc_base/rtc_certificate.h"
44 #include "rtc_base/socket_address.h"
45 #include "rtc_base/ssl_identity.h"
46 #include "rtc_base/ssl_stream_adapter.h"
47 #include "rtc_base/string_encode.h"
48 #include "rtc_base/third_party/base64/base64.h"
49 #include "rtc_base/thread.h"
50 #include "test/gmock.h"
51 #include "test/gtest.h"
52
53 using cricket::ConnectionInfo;
54 using cricket::SsrcReceiverInfo;
55 using cricket::TransportChannelStats;
56 using cricket::VideoMediaInfo;
57 using cricket::VideoReceiverInfo;
58 using cricket::VideoSenderInfo;
59 using cricket::VoiceMediaInfo;
60 using cricket::VoiceReceiverInfo;
61 using cricket::VoiceSenderInfo;
62 using ::testing::_;
63 using ::testing::AtMost;
64 using ::testing::Return;
65 using ::testing::UnorderedElementsAre;
66
67 namespace webrtc {
68
69 namespace internal {
70 // This value comes from openssl/tls1.h
71 static const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
72 } // namespace internal
73
74 // Error return values
75 const char kNotFound[] = "NOT FOUND";
76
77 // Constant names for track identification.
78 const char kLocalTrackId[] = "local_track_id";
79 const char kRemoteTrackId[] = "remote_track_id";
80 const uint32_t kSsrcOfTrack = 1234;
81
82 class FakeAudioProcessor : public AudioProcessorInterface {
83 public:
FakeAudioProcessor()84 FakeAudioProcessor() {}
~FakeAudioProcessor()85 ~FakeAudioProcessor() {}
86
87 private:
GetStats(bool has_recv_streams)88 AudioProcessorInterface::AudioProcessorStatistics GetStats(
89 bool has_recv_streams) override {
90 AudioProcessorStatistics stats;
91 if (has_recv_streams) {
92 stats.apm_statistics.echo_return_loss = 2.0;
93 stats.apm_statistics.echo_return_loss_enhancement = 3.0;
94 stats.apm_statistics.delay_median_ms = 4;
95 stats.apm_statistics.delay_standard_deviation_ms = 5;
96 }
97 return stats;
98 }
99 };
100
101 class FakeAudioTrack : public MediaStreamTrack<AudioTrackInterface> {
102 public:
FakeAudioTrack(const std::string & id)103 explicit FakeAudioTrack(const std::string& id)
104 : MediaStreamTrack<AudioTrackInterface>(id),
105 processor_(rtc::make_ref_counted<FakeAudioProcessor>()) {}
kind() const106 std::string kind() const override { return "audio"; }
GetSource() const107 AudioSourceInterface* GetSource() const override { return NULL; }
AddSink(AudioTrackSinkInterface * sink)108 void AddSink(AudioTrackSinkInterface* sink) override {}
RemoveSink(AudioTrackSinkInterface * sink)109 void RemoveSink(AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)110 bool GetSignalLevel(int* level) override {
111 *level = 1;
112 return true;
113 }
GetAudioProcessor()114 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
115 return processor_;
116 }
117
118 private:
119 rtc::scoped_refptr<FakeAudioProcessor> processor_;
120 };
121
122 // This fake audio processor is used to verify that the undesired initial values
123 // (-1) will be filtered out.
124 class FakeAudioProcessorWithInitValue : public AudioProcessorInterface {
125 public:
FakeAudioProcessorWithInitValue()126 FakeAudioProcessorWithInitValue() {}
~FakeAudioProcessorWithInitValue()127 ~FakeAudioProcessorWithInitValue() {}
128
129 private:
GetStats(bool)130 AudioProcessorInterface::AudioProcessorStatistics GetStats(
131 bool /*has_recv_streams*/) override {
132 AudioProcessorStatistics stats;
133 return stats;
134 }
135 };
136
137 class FakeAudioTrackWithInitValue
138 : public MediaStreamTrack<AudioTrackInterface> {
139 public:
FakeAudioTrackWithInitValue(const std::string & id)140 explicit FakeAudioTrackWithInitValue(const std::string& id)
141 : MediaStreamTrack<AudioTrackInterface>(id),
142 processor_(rtc::make_ref_counted<FakeAudioProcessorWithInitValue>()) {}
kind() const143 std::string kind() const override { return "audio"; }
GetSource() const144 AudioSourceInterface* GetSource() const override { return NULL; }
AddSink(AudioTrackSinkInterface * sink)145 void AddSink(AudioTrackSinkInterface* sink) override {}
RemoveSink(AudioTrackSinkInterface * sink)146 void RemoveSink(AudioTrackSinkInterface* sink) override {}
GetSignalLevel(int * level)147 bool GetSignalLevel(int* level) override {
148 *level = 1;
149 return true;
150 }
GetAudioProcessor()151 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override {
152 return processor_;
153 }
154
155 private:
156 rtc::scoped_refptr<FakeAudioProcessorWithInitValue> processor_;
157 };
158
GetValue(const StatsReport * report,StatsReport::StatsValueName name,std::string * value)159 bool GetValue(const StatsReport* report,
160 StatsReport::StatsValueName name,
161 std::string* value) {
162 const StatsReport::Value* v = report->FindValue(name);
163 if (!v)
164 return false;
165 *value = v->ToString();
166 return true;
167 }
168
ExtractStatsValue(const StatsReport::StatsType & type,const StatsReports & reports,StatsReport::StatsValueName name)169 std::string ExtractStatsValue(const StatsReport::StatsType& type,
170 const StatsReports& reports,
171 StatsReport::StatsValueName name) {
172 for (const auto* r : reports) {
173 std::string ret;
174 if (r->type() == type && GetValue(r, name, &ret))
175 return ret;
176 }
177
178 return kNotFound;
179 }
180
TypedIdFromIdString(StatsReport::StatsType type,const std::string & value)181 StatsReport::Id TypedIdFromIdString(StatsReport::StatsType type,
182 const std::string& value) {
183 EXPECT_FALSE(value.empty());
184 StatsReport::Id id;
185 if (value.empty())
186 return id;
187
188 // This has assumptions about how the ID is constructed. As is, this is
189 // OK since this is for testing purposes only, but if we ever need this
190 // in production, we should add a generic method that does this.
191 size_t index = value.find('_');
192 EXPECT_NE(index, std::string::npos);
193 if (index == std::string::npos || index == (value.length() - 1))
194 return id;
195
196 id = StatsReport::NewTypedId(type, value.substr(index + 1));
197 EXPECT_EQ(id->ToString(), value);
198 return id;
199 }
200
IdFromCertIdString(const std::string & cert_id)201 StatsReport::Id IdFromCertIdString(const std::string& cert_id) {
202 return TypedIdFromIdString(StatsReport::kStatsReportTypeCertificate, cert_id);
203 }
204
205 // Finds the `n`-th report of type `type` in `reports`.
206 // `n` starts from 1 for finding the first report.
FindNthReportByType(const StatsReports & reports,const StatsReport::StatsType & type,int n)207 const StatsReport* FindNthReportByType(const StatsReports& reports,
208 const StatsReport::StatsType& type,
209 int n) {
210 for (size_t i = 0; i < reports.size(); ++i) {
211 if (reports[i]->type() == type) {
212 n--;
213 if (n == 0)
214 return reports[i];
215 }
216 }
217 return nullptr;
218 }
219
220 // Returns the value of the stat identified by `name` in the `n`-th report of
221 // type `type` in `reports`.
222 // `n` starts from 1 for finding the first report.
223 // If either the `n`-th report is not found, or the stat is not present in that
224 // report, then nullopt is returned.
GetValueInNthReportByType(const StatsReports & reports,StatsReport::StatsType type,StatsReport::StatsValueName name,int n)225 absl::optional<std::string> GetValueInNthReportByType(
226 const StatsReports& reports,
227 StatsReport::StatsType type,
228 StatsReport::StatsValueName name,
229 int n) {
230 const StatsReport* report = FindNthReportByType(reports, type, n);
231 if (!report) {
232 return absl::nullopt;
233 }
234 std::string value;
235 if (!GetValue(report, name, &value)) {
236 return absl::nullopt;
237 }
238 return value;
239 }
240
GetReportsByType(const StatsReports & reports,StatsReport::StatsType type)241 std::vector<const StatsReport*> GetReportsByType(const StatsReports& reports,
242 StatsReport::StatsType type) {
243 std::vector<const StatsReport*> filtered_reports;
244 for (const StatsReport* report : reports) {
245 if (report->type() == type) {
246 filtered_reports.push_back(report);
247 }
248 }
249 return filtered_reports;
250 }
251
FindReportById(const StatsReports & reports,const StatsReport::Id & id)252 const StatsReport* FindReportById(const StatsReports& reports,
253 const StatsReport::Id& id) {
254 for (const auto* r : reports) {
255 if (r->id()->Equals(id))
256 return r;
257 }
258 return nullptr;
259 }
260
ExtractSsrcStatsValue(const StatsReports & reports,StatsReport::StatsValueName name)261 std::string ExtractSsrcStatsValue(const StatsReports& reports,
262 StatsReport::StatsValueName name) {
263 return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name);
264 }
265
ExtractBweStatsValue(const StatsReports & reports,StatsReport::StatsValueName name)266 std::string ExtractBweStatsValue(const StatsReports& reports,
267 StatsReport::StatsValueName name) {
268 return ExtractStatsValue(StatsReport::kStatsReportTypeBwe, reports, name);
269 }
270
DerToPem(const std::string & der)271 std::string DerToPem(const std::string& der) {
272 return rtc::SSLIdentity::DerToPem(
273 rtc::kPemTypeCertificate,
274 reinterpret_cast<const unsigned char*>(der.c_str()), der.length());
275 }
276
DersToPems(const std::vector<std::string> & ders)277 std::vector<std::string> DersToPems(const std::vector<std::string>& ders) {
278 std::vector<std::string> pems(ders.size());
279 absl::c_transform(ders, pems.begin(), DerToPem);
280 return pems;
281 }
282
CheckCertChainReports(const StatsReports & reports,const std::vector<std::string> & ders,const StatsReport::Id & start_id)283 void CheckCertChainReports(const StatsReports& reports,
284 const std::vector<std::string>& ders,
285 const StatsReport::Id& start_id) {
286 StatsReport::Id cert_id;
287 const StatsReport::Id* certificate_id = &start_id;
288 size_t i = 0;
289 while (true) {
290 const StatsReport* report = FindReportById(reports, *certificate_id);
291 ASSERT_TRUE(report != NULL);
292
293 std::string der_base64;
294 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDer, &der_base64));
295 std::string der = rtc::Base64::Decode(der_base64, rtc::Base64::DO_STRICT);
296 EXPECT_EQ(ders[i], der);
297
298 std::string fingerprint_algorithm;
299 EXPECT_TRUE(GetValue(report,
300 StatsReport::kStatsValueNameFingerprintAlgorithm,
301 &fingerprint_algorithm));
302 // The digest algorithm for a FakeSSLCertificate is always SHA-1.
303 std::string sha_1_str = rtc::DIGEST_SHA_1;
304 EXPECT_EQ(sha_1_str, fingerprint_algorithm);
305
306 std::string fingerprint;
307 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameFingerprint,
308 &fingerprint));
309 EXPECT_FALSE(fingerprint.empty());
310
311 ++i;
312 std::string issuer_id;
313 if (!GetValue(report, StatsReport::kStatsValueNameIssuerId, &issuer_id)) {
314 break;
315 }
316
317 cert_id = IdFromCertIdString(issuer_id);
318 certificate_id = &cert_id;
319 }
320 EXPECT_EQ(ders.size(), i);
321 }
322
VerifyVoiceReceiverInfoReport(const StatsReport * report,const cricket::VoiceReceiverInfo & info)323 void VerifyVoiceReceiverInfoReport(const StatsReport* report,
324 const cricket::VoiceReceiverInfo& info) {
325 std::string value_in_report;
326 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioOutputLevel,
327 &value_in_report));
328 EXPECT_EQ(rtc::ToString(info.audio_level), value_in_report);
329 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesReceived,
330 &value_in_report));
331 EXPECT_EQ(rtc::ToString(info.payload_bytes_rcvd +
332 info.header_and_padding_bytes_rcvd),
333 value_in_report);
334 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
335 &value_in_report));
336 EXPECT_EQ(rtc::ToString(info.jitter_ms), value_in_report);
337 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterBufferMs,
338 &value_in_report));
339 EXPECT_EQ(rtc::ToString(info.jitter_buffer_ms), value_in_report);
340 EXPECT_TRUE(GetValue(report,
341 StatsReport::kStatsValueNamePreferredJitterBufferMs,
342 &value_in_report));
343 EXPECT_EQ(rtc::ToString(info.jitter_buffer_preferred_ms), value_in_report);
344 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCurrentDelayMs,
345 &value_in_report));
346 EXPECT_EQ(rtc::ToString(info.delay_estimate_ms), value_in_report);
347 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameExpandRate,
348 &value_in_report));
349 EXPECT_EQ(rtc::ToString(info.expand_rate), value_in_report);
350 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSpeechExpandRate,
351 &value_in_report));
352 EXPECT_EQ(rtc::ToString(info.speech_expand_rate), value_in_report);
353 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate,
354 &value_in_report));
355 EXPECT_EQ(rtc::ToString(info.accelerate_rate), value_in_report);
356 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate,
357 &value_in_report));
358 EXPECT_EQ(rtc::ToString(info.preemptive_expand_rate), value_in_report);
359 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate,
360 &value_in_report));
361 EXPECT_EQ(rtc::ToString(info.secondary_decoded_rate), value_in_report);
362 EXPECT_TRUE(GetValue(report,
363 StatsReport::kStatsValueNameSecondaryDiscardedRate,
364 &value_in_report));
365 EXPECT_EQ(rtc::ToString(info.secondary_discarded_rate), value_in_report);
366 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsReceived,
367 &value_in_report));
368 EXPECT_EQ(rtc::ToString(info.packets_rcvd), value_in_report);
369 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTSG,
370 &value_in_report));
371 EXPECT_EQ(rtc::ToString(info.decoding_calls_to_silence_generator),
372 value_in_report);
373 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCTN,
374 &value_in_report));
375 EXPECT_EQ(rtc::ToString(info.decoding_calls_to_neteq), value_in_report);
376 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingNormal,
377 &value_in_report));
378 EXPECT_EQ(rtc::ToString(info.decoding_normal), value_in_report);
379 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLC,
380 &value_in_report));
381 EXPECT_EQ(rtc::ToString(info.decoding_plc), value_in_report);
382 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCodecPLC,
383 &value_in_report));
384 EXPECT_EQ(rtc::ToString(info.decoding_codec_plc), value_in_report);
385 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingCNG,
386 &value_in_report));
387 EXPECT_EQ(rtc::ToString(info.decoding_cng), value_in_report);
388 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingPLCCNG,
389 &value_in_report));
390 EXPECT_EQ(rtc::ToString(info.decoding_plc_cng), value_in_report);
391 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameDecodingMutedOutput,
392 &value_in_report));
393 EXPECT_EQ(rtc::ToString(info.decoding_muted_output), value_in_report);
394 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
395 &value_in_report));
396 }
397
VerifyVoiceSenderInfoReport(const StatsReport * report,const cricket::VoiceSenderInfo & sinfo)398 void VerifyVoiceSenderInfoReport(const StatsReport* report,
399 const cricket::VoiceSenderInfo& sinfo) {
400 std::string value_in_report;
401 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameCodecName,
402 &value_in_report));
403 EXPECT_EQ(sinfo.codec_name, value_in_report);
404 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameBytesSent,
405 &value_in_report));
406 EXPECT_EQ(rtc::ToString(sinfo.payload_bytes_sent +
407 sinfo.header_and_padding_bytes_sent),
408 value_in_report);
409 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsSent,
410 &value_in_report));
411 EXPECT_EQ(rtc::ToString(sinfo.packets_sent), value_in_report);
412 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
413 &value_in_report));
414 EXPECT_EQ(rtc::ToString(sinfo.packets_lost), value_in_report);
415 EXPECT_TRUE(
416 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
417 EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
418 EXPECT_TRUE(
419 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
420 EXPECT_EQ(rtc::ToString(sinfo.rtt_ms), value_in_report);
421 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
422 &value_in_report));
423 EXPECT_EQ(rtc::ToString(sinfo.jitter_ms), value_in_report);
424 if (sinfo.apm_statistics.delay_median_ms) {
425 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
426 &value_in_report));
427 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_median_ms),
428 value_in_report);
429 } else {
430 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
431 &value_in_report));
432 }
433 if (sinfo.apm_statistics.delay_standard_deviation_ms) {
434 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
435 &value_in_report));
436 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.delay_standard_deviation_ms),
437 value_in_report);
438 } else {
439 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
440 &value_in_report));
441 }
442 if (sinfo.apm_statistics.echo_return_loss) {
443 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
444 &value_in_report));
445 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss),
446 value_in_report);
447 } else {
448 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoReturnLoss,
449 &value_in_report));
450 }
451 if (sinfo.apm_statistics.echo_return_loss_enhancement) {
452 EXPECT_TRUE(GetValue(report,
453 StatsReport::kStatsValueNameEchoReturnLossEnhancement,
454 &value_in_report));
455 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.echo_return_loss_enhancement),
456 value_in_report);
457 } else {
458 EXPECT_FALSE(GetValue(report,
459 StatsReport::kStatsValueNameEchoReturnLossEnhancement,
460 &value_in_report));
461 }
462 if (sinfo.apm_statistics.residual_echo_likelihood) {
463 EXPECT_TRUE(GetValue(report,
464 StatsReport::kStatsValueNameResidualEchoLikelihood,
465 &value_in_report));
466 EXPECT_EQ(rtc::ToString(*sinfo.apm_statistics.residual_echo_likelihood),
467 value_in_report);
468 } else {
469 EXPECT_FALSE(GetValue(report,
470 StatsReport::kStatsValueNameResidualEchoLikelihood,
471 &value_in_report));
472 }
473 if (sinfo.apm_statistics.residual_echo_likelihood_recent_max) {
474 EXPECT_TRUE(GetValue(
475 report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
476 &value_in_report));
477 EXPECT_EQ(rtc::ToString(
478 *sinfo.apm_statistics.residual_echo_likelihood_recent_max),
479 value_in_report);
480 } else {
481 EXPECT_FALSE(GetValue(
482 report, StatsReport::kStatsValueNameResidualEchoLikelihoodRecentMax,
483 &value_in_report));
484 }
485 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
486 &value_in_report));
487 EXPECT_EQ(rtc::ToString(sinfo.audio_level), value_in_report);
488 EXPECT_TRUE(GetValue(report,
489 StatsReport::kStatsValueNameAnaBitrateActionCounter,
490 &value_in_report));
491 ASSERT_TRUE(sinfo.ana_statistics.bitrate_action_counter);
492 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.bitrate_action_counter),
493 value_in_report);
494 EXPECT_TRUE(GetValue(report,
495 StatsReport::kStatsValueNameAnaChannelActionCounter,
496 &value_in_report));
497 ASSERT_TRUE(sinfo.ana_statistics.channel_action_counter);
498 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.channel_action_counter),
499 value_in_report);
500 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaDtxActionCounter,
501 &value_in_report));
502 ASSERT_TRUE(sinfo.ana_statistics.dtx_action_counter);
503 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.dtx_action_counter),
504 value_in_report);
505 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAnaFecActionCounter,
506 &value_in_report));
507 ASSERT_TRUE(sinfo.ana_statistics.fec_action_counter);
508 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.fec_action_counter),
509 value_in_report);
510 EXPECT_TRUE(GetValue(
511 report, StatsReport::kStatsValueNameAnaFrameLengthIncreaseCounter,
512 &value_in_report));
513 ASSERT_TRUE(sinfo.ana_statistics.frame_length_increase_counter);
514 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_increase_counter),
515 value_in_report);
516 EXPECT_TRUE(GetValue(
517 report, StatsReport::kStatsValueNameAnaFrameLengthDecreaseCounter,
518 &value_in_report));
519 ASSERT_TRUE(sinfo.ana_statistics.frame_length_decrease_counter);
520 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.frame_length_decrease_counter),
521 value_in_report);
522 EXPECT_TRUE(GetValue(report,
523 StatsReport::kStatsValueNameAnaUplinkPacketLossFraction,
524 &value_in_report));
525 ASSERT_TRUE(sinfo.ana_statistics.uplink_packet_loss_fraction);
526 EXPECT_EQ(rtc::ToString(*sinfo.ana_statistics.uplink_packet_loss_fraction),
527 value_in_report);
528 }
529
530 // Helper methods to avoid duplication of code.
InitVoiceSenderInfo(cricket::VoiceSenderInfo * voice_sender_info,uint32_t ssrc=kSsrcOfTrack)531 void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info,
532 uint32_t ssrc = kSsrcOfTrack) {
533 voice_sender_info->add_ssrc(ssrc);
534 voice_sender_info->codec_name = "fake_codec";
535 voice_sender_info->payload_bytes_sent = 88;
536 voice_sender_info->header_and_padding_bytes_sent = 12;
537 voice_sender_info->packets_sent = 101;
538 voice_sender_info->rtt_ms = 102;
539 voice_sender_info->fraction_lost = 103;
540 voice_sender_info->jitter_ms = 104;
541 voice_sender_info->packets_lost = 105;
542 voice_sender_info->audio_level = 107;
543 voice_sender_info->apm_statistics.echo_return_loss = 108;
544 voice_sender_info->apm_statistics.echo_return_loss_enhancement = 109;
545 voice_sender_info->apm_statistics.delay_median_ms = 110;
546 voice_sender_info->apm_statistics.delay_standard_deviation_ms = 111;
547 voice_sender_info->ana_statistics.bitrate_action_counter = 112;
548 voice_sender_info->ana_statistics.channel_action_counter = 113;
549 voice_sender_info->ana_statistics.dtx_action_counter = 114;
550 voice_sender_info->ana_statistics.fec_action_counter = 115;
551 voice_sender_info->ana_statistics.frame_length_increase_counter = 116;
552 voice_sender_info->ana_statistics.frame_length_decrease_counter = 117;
553 voice_sender_info->ana_statistics.uplink_packet_loss_fraction = 118.0;
554 }
555
UpdateVoiceSenderInfoFromAudioTrack(AudioTrackInterface * audio_track,cricket::VoiceSenderInfo * voice_sender_info,bool has_remote_tracks)556 void UpdateVoiceSenderInfoFromAudioTrack(
557 AudioTrackInterface* audio_track,
558 cricket::VoiceSenderInfo* voice_sender_info,
559 bool has_remote_tracks) {
560 audio_track->GetSignalLevel(&voice_sender_info->audio_level);
561 AudioProcessorInterface::AudioProcessorStatistics audio_processor_stats =
562 audio_track->GetAudioProcessor()->GetStats(has_remote_tracks);
563 voice_sender_info->apm_statistics = audio_processor_stats.apm_statistics;
564 }
565
InitVoiceReceiverInfo(cricket::VoiceReceiverInfo * voice_receiver_info)566 void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) {
567 voice_receiver_info->add_ssrc(kSsrcOfTrack);
568 voice_receiver_info->payload_bytes_rcvd = 98;
569 voice_receiver_info->header_and_padding_bytes_rcvd = 12;
570 voice_receiver_info->packets_rcvd = 111;
571 voice_receiver_info->packets_lost = 114;
572 voice_receiver_info->jitter_ms = 116;
573 voice_receiver_info->jitter_buffer_ms = 117;
574 voice_receiver_info->jitter_buffer_preferred_ms = 118;
575 voice_receiver_info->delay_estimate_ms = 119;
576 voice_receiver_info->audio_level = 120;
577 voice_receiver_info->expand_rate = 121;
578 voice_receiver_info->speech_expand_rate = 122;
579 voice_receiver_info->secondary_decoded_rate = 123;
580 voice_receiver_info->accelerate_rate = 124;
581 voice_receiver_info->preemptive_expand_rate = 125;
582 voice_receiver_info->secondary_discarded_rate = 126;
583 voice_receiver_info->decoding_codec_plc = 127;
584 }
585
586 class LegacyStatsCollectorForTest : public LegacyStatsCollector {
587 public:
LegacyStatsCollectorForTest(PeerConnectionInternal * pc)588 explicit LegacyStatsCollectorForTest(PeerConnectionInternal* pc)
589 : LegacyStatsCollector(pc), time_now_(19477) {}
590
GetTimeNow()591 double GetTimeNow() override { return time_now_; }
592
593 private:
594 double time_now_;
595 };
596
597 class LegacyStatsCollectorTest : public ::testing::Test {
598 protected:
CreatePeerConnection()599 rtc::scoped_refptr<FakePeerConnectionForStats> CreatePeerConnection() {
600 return rtc::make_ref_counted<FakePeerConnectionForStats>();
601 }
602
CreateStatsCollector(PeerConnectionInternal * pc)603 std::unique_ptr<LegacyStatsCollectorForTest> CreateStatsCollector(
604 PeerConnectionInternal* pc) {
605 return std::make_unique<LegacyStatsCollectorForTest>(pc);
606 }
607
VerifyAudioTrackStats(FakeAudioTrack * audio_track,LegacyStatsCollectorForTest * stats,const VoiceMediaInfo & voice_info,StatsReports * reports)608 void VerifyAudioTrackStats(FakeAudioTrack* audio_track,
609 LegacyStatsCollectorForTest* stats,
610 const VoiceMediaInfo& voice_info,
611 StatsReports* reports) {
612 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
613 stats->InvalidateCache();
614 stats->GetStats(nullptr, reports);
615
616 // Verify the existence of the track report.
617 const StatsReport* report =
618 FindNthReportByType(*reports, StatsReport::kStatsReportTypeSsrc, 1);
619 ASSERT_TRUE(report);
620 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
621 std::string track_id =
622 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameTrackId);
623 EXPECT_EQ(audio_track->id(), track_id);
624 std::string ssrc_id =
625 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameSsrc);
626 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
627
628 std::string media_type =
629 ExtractSsrcStatsValue(*reports, StatsReport::kStatsValueNameMediaType);
630 EXPECT_EQ("audio", media_type);
631
632 // Verifies the values in the track report.
633 if (!voice_info.senders.empty()) {
634 VerifyVoiceSenderInfoReport(report, voice_info.senders[0]);
635 }
636 if (!voice_info.receivers.empty()) {
637 VerifyVoiceReceiverInfoReport(report, voice_info.receivers[0]);
638 }
639
640 // Verify we get the same result by passing a track to GetStats().
641 StatsReports track_reports; // returned values.
642 stats->GetStats(audio_track, &track_reports);
643 const StatsReport* track_report = FindNthReportByType(
644 track_reports, StatsReport::kStatsReportTypeSsrc, 1);
645 ASSERT_TRUE(track_report);
646 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
647 track_id = ExtractSsrcStatsValue(track_reports,
648 StatsReport::kStatsValueNameTrackId);
649 EXPECT_EQ(audio_track->id(), track_id);
650 ssrc_id =
651 ExtractSsrcStatsValue(track_reports, StatsReport::kStatsValueNameSsrc);
652 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
653 if (!voice_info.senders.empty()) {
654 VerifyVoiceSenderInfoReport(track_report, voice_info.senders[0]);
655 }
656 if (!voice_info.receivers.empty()) {
657 VerifyVoiceReceiverInfoReport(track_report, voice_info.receivers[0]);
658 }
659 }
660
TestCertificateReports(const rtc::FakeSSLIdentity & local_identity,const std::vector<std::string> & local_ders,const rtc::FakeSSLIdentity & remote_identity,const std::vector<std::string> & remote_ders)661 void TestCertificateReports(const rtc::FakeSSLIdentity& local_identity,
662 const std::vector<std::string>& local_ders,
663 const rtc::FakeSSLIdentity& remote_identity,
664 const std::vector<std::string>& remote_ders) {
665 const std::string kTransportName = "transport";
666
667 auto pc = CreatePeerConnection();
668 auto stats = CreateStatsCollector(pc.get());
669
670 pc->AddVoiceChannel("audio", kTransportName);
671
672 // Fake stats to process.
673 TransportChannelStats channel_stats;
674 channel_stats.component = 1;
675 channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80;
676 channel_stats.ssl_cipher_suite =
677 internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
678 pc->SetTransportStats(kTransportName, channel_stats);
679
680 // Fake certificate to report.
681 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate(
682 rtc::RTCCertificate::Create(local_identity.Clone()));
683 pc->SetLocalCertificate(kTransportName, local_certificate);
684 pc->SetRemoteCertChain(kTransportName,
685 remote_identity.cert_chain().Clone());
686
687 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
688
689 StatsReports reports;
690 stats->GetStats(nullptr, &reports);
691
692 const StatsReport* channel_report =
693 FindNthReportByType(reports, StatsReport::kStatsReportTypeComponent, 1);
694 EXPECT_TRUE(channel_report);
695
696 // Check local certificate chain.
697 std::string local_certificate_id =
698 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
699 StatsReport::kStatsValueNameLocalCertificateId);
700 if (local_ders.size() > 0) {
701 EXPECT_NE(kNotFound, local_certificate_id);
702 StatsReport::Id id(IdFromCertIdString(local_certificate_id));
703 CheckCertChainReports(reports, local_ders, id);
704 } else {
705 EXPECT_EQ(kNotFound, local_certificate_id);
706 }
707
708 // Check remote certificate chain.
709 std::string remote_certificate_id =
710 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
711 StatsReport::kStatsValueNameRemoteCertificateId);
712 if (remote_ders.size() > 0) {
713 EXPECT_NE(kNotFound, remote_certificate_id);
714 StatsReport::Id id(IdFromCertIdString(remote_certificate_id));
715 CheckCertChainReports(reports, remote_ders, id);
716 } else {
717 EXPECT_EQ(kNotFound, remote_certificate_id);
718 }
719
720 // Check negotiated ciphers.
721 std::string dtls_cipher_suite =
722 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
723 StatsReport::kStatsValueNameDtlsCipher);
724 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName(
725 internal::TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA),
726 dtls_cipher_suite);
727 std::string srtp_crypto_suite =
728 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
729 StatsReport::kStatsValueNameSrtpCipher);
730 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::kSrtpAes128CmSha1_80),
731 srtp_crypto_suite);
732 }
733
734 private:
735 rtc::AutoThread main_thread_;
736 };
737
CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc)738 static rtc::scoped_refptr<MockRtpSenderInternal> CreateMockSender(
739 rtc::scoped_refptr<MediaStreamTrackInterface> track,
740 uint32_t ssrc) {
741 auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
742 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
743 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc));
744 EXPECT_CALL(*sender, media_type())
745 .WillRepeatedly(
746 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
747 ? cricket::MEDIA_TYPE_AUDIO
748 : cricket::MEDIA_TYPE_VIDEO));
749 EXPECT_CALL(*sender, SetMediaChannel(_)).Times(AtMost(2));
750 EXPECT_CALL(*sender, SetTransceiverAsStopped()).Times(AtMost(1));
751 EXPECT_CALL(*sender, Stop());
752 return sender;
753 }
754
CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,uint32_t ssrc)755 static rtc::scoped_refptr<MockRtpReceiverInternal> CreateMockReceiver(
756 rtc::scoped_refptr<MediaStreamTrackInterface> track,
757 uint32_t ssrc) {
758 auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
759 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
760 EXPECT_CALL(*receiver, ssrc()).WillRepeatedly(Return(ssrc));
761 EXPECT_CALL(*receiver, media_type())
762 .WillRepeatedly(
763 Return(track->kind() == MediaStreamTrackInterface::kAudioKind
764 ? cricket::MEDIA_TYPE_AUDIO
765 : cricket::MEDIA_TYPE_VIDEO));
766 EXPECT_CALL(*receiver, SetMediaChannel(_)).WillRepeatedly(Return());
767 EXPECT_CALL(*receiver, Stop()).WillRepeatedly(Return());
768 return receiver;
769 }
770
771 class StatsCollectorTrackTest : public LegacyStatsCollectorTest,
772 public ::testing::WithParamInterface<bool> {
773 public:
774 // Adds a outgoing video track with a given SSRC into the stats.
775 // If GetParam() returns true, the track is also inserted into the local
776 // stream, which is created if necessary.
AddOutgoingVideoTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)777 void AddOutgoingVideoTrack(FakePeerConnectionForStats* pc,
778 LegacyStatsCollectorForTest* stats) {
779 video_track_ = VideoTrack::Create(
780 kLocalTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
781 if (GetParam()) {
782 if (!stream_)
783 stream_ = MediaStream::Create("streamid");
784 stream_->AddTrack(video_track());
785 stats->AddStream(stream_.get());
786 } else {
787 stats->AddTrack(video_track_.get());
788 }
789 pc->AddSender(CreateMockSender(video_track_, kSsrcOfTrack));
790 }
791
792 // Adds a incoming video track with a given SSRC into the stats.
AddIncomingVideoTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)793 void AddIncomingVideoTrack(FakePeerConnectionForStats* pc,
794 LegacyStatsCollectorForTest* stats) {
795 video_track_ = VideoTrack::Create(
796 kRemoteTrackId, FakeVideoTrackSource::Create(), rtc::Thread::Current());
797 if (GetParam()) {
798 stream_ = MediaStream::Create("streamid");
799 stream_->AddTrack(video_track());
800 stats->AddStream(stream_.get());
801 } else {
802 stats->AddTrack(video_track_.get());
803 }
804 pc->AddReceiver(CreateMockReceiver(video_track_, kSsrcOfTrack));
805 }
806
807 // Adds a outgoing audio track with a given SSRC into the stats,
808 // and register it into the stats object.
809 // If GetParam() returns true, the track is also inserted into the local
810 // stream, which is created if necessary.
AddOutgoingAudioTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)811 rtc::scoped_refptr<RtpSenderInterface> AddOutgoingAudioTrack(
812 FakePeerConnectionForStats* pc,
813 LegacyStatsCollectorForTest* stats) {
814 audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kLocalTrackId);
815 if (GetParam()) {
816 if (!stream_)
817 stream_ = MediaStream::Create("streamid");
818 stream_->AddTrack(audio_track());
819 stats->AddStream(stream_.get());
820 } else {
821 stats->AddTrack(audio_track_.get());
822 }
823 return pc->AddSender(CreateMockSender(audio_track_, kSsrcOfTrack));
824 }
825
826 // Adds a incoming audio track with a given SSRC into the stats.
AddIncomingAudioTrack(FakePeerConnectionForStats * pc,LegacyStatsCollectorForTest * stats)827 void AddIncomingAudioTrack(FakePeerConnectionForStats* pc,
828 LegacyStatsCollectorForTest* stats) {
829 audio_track_ = rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
830 if (GetParam()) {
831 if (stream_ == nullptr)
832 stream_ = MediaStream::Create("streamid");
833 stream_->AddTrack(audio_track());
834 stats->AddStream(stream_.get());
835 } else {
836 stats->AddTrack(audio_track_.get());
837 }
838 pc->AddReceiver(CreateMockReceiver(audio_track_, kSsrcOfTrack));
839 }
840
audio_track()841 rtc::scoped_refptr<AudioTrackInterface> audio_track() { return audio_track_; }
video_track()842 rtc::scoped_refptr<VideoTrackInterface> video_track() { return video_track_; }
843
844 rtc::scoped_refptr<MediaStream> stream_;
845 rtc::scoped_refptr<VideoTrack> video_track_;
846 rtc::scoped_refptr<FakeAudioTrack> audio_track_;
847 };
848
TEST_F(LegacyStatsCollectorTest,FilterOutNegativeDataChannelId)849 TEST_F(LegacyStatsCollectorTest, FilterOutNegativeDataChannelId) {
850 auto pc = CreatePeerConnection();
851 auto stats = CreateStatsCollector(pc.get());
852
853 pc->AddSctpDataChannel("hacks");
854
855 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
856 StatsReports reports;
857 stats->GetStats(nullptr, &reports);
858
859 const StatsReport* report =
860 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
861
862 std::string value_in_report;
863 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameDataChannelId,
864 &value_in_report));
865 }
866
867 // Verify that ExtractDataInfo populates reports.
TEST_F(LegacyStatsCollectorTest,ExtractDataInfo)868 TEST_F(LegacyStatsCollectorTest, ExtractDataInfo) {
869 const std::string kDataChannelLabel = "hacks";
870 constexpr int kDataChannelId = 31337;
871 const std::string kConnectingString = DataChannelInterface::DataStateString(
872 DataChannelInterface::DataState::kConnecting);
873
874 auto pc = CreatePeerConnection();
875 auto stats = CreateStatsCollector(pc.get());
876
877 InternalDataChannelInit init;
878 init.id = kDataChannelId;
879 pc->AddSctpDataChannel(kDataChannelLabel, init);
880
881 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
882 StatsReports reports;
883 stats->GetStats(nullptr, &reports);
884
885 const StatsReport* report =
886 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1);
887
888 StatsReport::Id report_id = StatsReport::NewTypedIntId(
889 StatsReport::kStatsReportTypeDataChannel, kDataChannelId);
890
891 EXPECT_TRUE(report_id->Equals(report->id()));
892
893 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
894 EXPECT_EQ(kDataChannelLabel,
895 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
896 StatsReport::kStatsValueNameLabel));
897 EXPECT_EQ(rtc::ToString(kDataChannelId),
898 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
899 StatsReport::kStatsValueNameDataChannelId));
900 EXPECT_EQ(kConnectingString,
901 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
902 StatsReport::kStatsValueNameState));
903 EXPECT_EQ("",
904 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports,
905 StatsReport::kStatsValueNameProtocol));
906 }
907
908 // This test verifies that 64-bit counters are passed successfully.
TEST_P(StatsCollectorTrackTest,BytesCounterHandles64Bits)909 TEST_P(StatsCollectorTrackTest, BytesCounterHandles64Bits) {
910 // The number of bytes must be larger than 0xFFFFFFFF for this test.
911 constexpr int64_t kBytesSent = 12345678901234LL;
912
913 auto pc = CreatePeerConnection();
914 auto stats = CreateStatsCollector(pc.get());
915
916 VideoSenderInfo video_sender_info;
917 video_sender_info.add_ssrc(1234);
918 video_sender_info.payload_bytes_sent = kBytesSent;
919 video_sender_info.header_and_padding_bytes_sent = 0;
920 VideoMediaInfo video_info;
921 video_info.aggregated_senders.push_back(video_sender_info);
922
923 pc->AddVideoChannel("video", "transport", video_info);
924
925 AddOutgoingVideoTrack(pc.get(), stats.get());
926
927 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
928 StatsReports reports;
929 stats->GetStats(nullptr, &reports);
930
931 EXPECT_EQ(
932 rtc::ToString(kBytesSent),
933 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
934 }
935
936 // Test that audio BWE information is reported via stats.
TEST_P(StatsCollectorTrackTest,AudioBandwidthEstimationInfoIsReported)937 TEST_P(StatsCollectorTrackTest, AudioBandwidthEstimationInfoIsReported) {
938 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
939 // BWE.
940 constexpr int64_t kBytesSent = 12345678901234LL;
941 constexpr int kSendBandwidth = 1234567;
942 constexpr int kRecvBandwidth = 12345678;
943 constexpr int kPacerDelay = 123;
944
945 auto pc = CreatePeerConnection();
946 auto stats = CreateStatsCollector(pc.get());
947
948 VoiceSenderInfo voice_sender_info;
949 voice_sender_info.add_ssrc(1234);
950 voice_sender_info.payload_bytes_sent = kBytesSent - 12;
951 voice_sender_info.header_and_padding_bytes_sent = 12;
952 VoiceMediaInfo voice_info;
953 voice_info.senders.push_back(voice_sender_info);
954
955 auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
956 voice_media_channel->SetStats(voice_info);
957
958 AddOutgoingAudioTrack(pc.get(), stats.get());
959
960 Call::Stats call_stats;
961 call_stats.send_bandwidth_bps = kSendBandwidth;
962 call_stats.recv_bandwidth_bps = kRecvBandwidth;
963 call_stats.pacer_delay_ms = kPacerDelay;
964 pc->SetCallStats(call_stats);
965
966 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
967 StatsReports reports;
968 stats->GetStats(nullptr, &reports);
969
970 EXPECT_EQ(
971 rtc::ToString(kBytesSent),
972 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
973 EXPECT_EQ(rtc::ToString(kSendBandwidth),
974 ExtractBweStatsValue(
975 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
976 EXPECT_EQ(
977 rtc::ToString(kRecvBandwidth),
978 ExtractBweStatsValue(
979 reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
980 EXPECT_EQ(
981 rtc::ToString(kPacerDelay),
982 ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
983 }
984
985 // Test that video BWE information is reported via stats.
TEST_P(StatsCollectorTrackTest,VideoBandwidthEstimationInfoIsReported)986 TEST_P(StatsCollectorTrackTest, VideoBandwidthEstimationInfoIsReported) {
987 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
988 // BWE.
989 constexpr int64_t kBytesSent = 12345678901234LL;
990 constexpr int kSendBandwidth = 1234567;
991 constexpr int kRecvBandwidth = 12345678;
992 constexpr int kPacerDelay = 123;
993
994 auto pc = CreatePeerConnection();
995 auto stats = CreateStatsCollector(pc.get());
996
997 VideoSenderInfo video_sender_info;
998 video_sender_info.add_ssrc(1234);
999 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1000 video_sender_info.header_and_padding_bytes_sent = 12;
1001
1002 VideoMediaInfo video_info;
1003 video_info.aggregated_senders.push_back(video_sender_info);
1004
1005 pc->AddVideoChannel("video", "transport", video_info);
1006
1007 AddOutgoingVideoTrack(pc.get(), stats.get());
1008
1009 Call::Stats call_stats;
1010 call_stats.send_bandwidth_bps = kSendBandwidth;
1011 call_stats.recv_bandwidth_bps = kRecvBandwidth;
1012 call_stats.pacer_delay_ms = kPacerDelay;
1013 pc->SetCallStats(call_stats);
1014
1015 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1016 StatsReports reports;
1017 stats->GetStats(nullptr, &reports);
1018
1019 EXPECT_EQ(
1020 rtc::ToString(kBytesSent),
1021 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameBytesSent));
1022 EXPECT_EQ(rtc::ToString(kSendBandwidth),
1023 ExtractBweStatsValue(
1024 reports, StatsReport::kStatsValueNameAvailableSendBandwidth));
1025 EXPECT_EQ(
1026 rtc::ToString(kRecvBandwidth),
1027 ExtractBweStatsValue(
1028 reports, StatsReport::kStatsValueNameAvailableReceiveBandwidth));
1029 EXPECT_EQ(
1030 rtc::ToString(kPacerDelay),
1031 ExtractBweStatsValue(reports, StatsReport::kStatsValueNameBucketDelay));
1032 }
1033
1034 // This test verifies that an object of type "googSession" always
1035 // exists in the returned stats.
TEST_F(LegacyStatsCollectorTest,SessionObjectExists)1036 TEST_F(LegacyStatsCollectorTest, SessionObjectExists) {
1037 auto pc = CreatePeerConnection();
1038 auto stats = CreateStatsCollector(pc.get());
1039
1040 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1041 StatsReports reports;
1042 stats->GetStats(nullptr, &reports);
1043
1044 EXPECT_TRUE(
1045 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
1046 }
1047
1048 // This test verifies that only one object of type "googSession" exists
1049 // in the returned stats.
TEST_F(LegacyStatsCollectorTest,OnlyOneSessionObjectExists)1050 TEST_F(LegacyStatsCollectorTest, OnlyOneSessionObjectExists) {
1051 auto pc = CreatePeerConnection();
1052 auto stats = CreateStatsCollector(pc.get());
1053
1054 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1055 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1056 StatsReports reports;
1057 stats->GetStats(nullptr, &reports);
1058
1059 EXPECT_TRUE(
1060 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 1));
1061 EXPECT_FALSE(
1062 FindNthReportByType(reports, StatsReport::kStatsReportTypeSession, 2));
1063 }
1064
1065 // This test verifies that the empty track report exists in the returned stats
1066 // without calling StatsCollector::UpdateStats.
TEST_P(StatsCollectorTrackTest,TrackObjectExistsWithoutUpdateStats)1067 TEST_P(StatsCollectorTrackTest, TrackObjectExistsWithoutUpdateStats) {
1068 auto pc = CreatePeerConnection();
1069 auto stats = CreateStatsCollector(pc.get());
1070
1071 pc->AddVideoChannel("video", "transport");
1072 AddOutgoingVideoTrack(pc.get(), stats.get());
1073
1074 // Verfies the existence of the track report.
1075 StatsReports reports;
1076 stats->GetStats(nullptr, &reports);
1077 ASSERT_EQ(1u, reports.size());
1078 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type());
1079 EXPECT_EQ(0, reports[0]->timestamp());
1080
1081 std::string trackValue =
1082 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, reports,
1083 StatsReport::kStatsValueNameTrackId);
1084 EXPECT_EQ(kLocalTrackId, trackValue);
1085 }
1086
1087 // This test verifies that the empty track report exists in the returned stats
1088 // when StatsCollector::UpdateStats is called with ssrc stats.
TEST_P(StatsCollectorTrackTest,TrackAndSsrcObjectExistAfterUpdateSsrcStats)1089 TEST_P(StatsCollectorTrackTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
1090 constexpr int64_t kBytesSent = 12345678901234LL;
1091
1092 auto pc = CreatePeerConnection();
1093 auto stats = CreateStatsCollector(pc.get());
1094
1095 VideoSenderInfo video_sender_info;
1096 video_sender_info.add_ssrc(1234);
1097 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1098 video_sender_info.header_and_padding_bytes_sent = 12;
1099 VideoMediaInfo video_info;
1100 video_info.aggregated_senders.push_back(video_sender_info);
1101
1102 pc->AddVideoChannel("video", "transport", video_info);
1103
1104 AddOutgoingVideoTrack(pc.get(), stats.get());
1105
1106 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1107 StatsReports reports;
1108 stats->GetStats(nullptr, &reports);
1109
1110 // `reports` should contain at least one session report, one track report,
1111 // and one ssrc report.
1112 EXPECT_LE(3u, reports.size());
1113 const StatsReport* track_report =
1114 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1115 EXPECT_TRUE(track_report);
1116
1117 // Get report for the specific `track`.
1118 reports.clear();
1119 stats->GetStats(video_track_.get(), &reports);
1120 // `reports` should contain at least one session report, one track report,
1121 // and one ssrc report.
1122 EXPECT_LE(3u, reports.size());
1123 track_report =
1124 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1125 ASSERT_TRUE(track_report);
1126 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1127
1128 std::string ssrc_id =
1129 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1130 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1131
1132 std::string track_id =
1133 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1134 EXPECT_EQ(kLocalTrackId, track_id);
1135
1136 std::string media_type =
1137 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameMediaType);
1138 EXPECT_EQ("video", media_type);
1139 }
1140
1141 // This test verifies that an SSRC object has the identifier of a Transport
1142 // stats object, and that this transport stats object exists in stats.
TEST_P(StatsCollectorTrackTest,TransportObjectLinkedFromSsrcObject)1143 TEST_P(StatsCollectorTrackTest, TransportObjectLinkedFromSsrcObject) {
1144 constexpr int64_t kBytesSent = 12345678901234LL;
1145
1146 auto pc = CreatePeerConnection();
1147 auto stats = CreateStatsCollector(pc.get());
1148
1149 VideoSenderInfo video_sender_info;
1150 video_sender_info.add_ssrc(1234);
1151 video_sender_info.payload_bytes_sent = kBytesSent - 12;
1152 video_sender_info.header_and_padding_bytes_sent = 12;
1153 VideoMediaInfo video_info;
1154 video_info.aggregated_senders.push_back(video_sender_info);
1155
1156 pc->AddVideoChannel("video", "transport", video_info);
1157
1158 AddOutgoingVideoTrack(pc.get(), stats.get());
1159
1160 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1161 StatsReports reports;
1162 stats->GetStats(nullptr, &reports);
1163
1164 std::string transport_id =
1165 ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports,
1166 StatsReport::kStatsValueNameTransportId);
1167 ASSERT_NE(kNotFound, transport_id);
1168
1169 // Transport id component ID will always be 1.
1170 // This has assumptions about how the ID is constructed. As is, this is
1171 // OK since this is for testing purposes only, but if we ever need this
1172 // in production, we should add a generic method that does this.
1173 size_t index = transport_id.find('-');
1174 ASSERT_NE(std::string::npos, index);
1175 std::string content = transport_id.substr(index + 1);
1176 index = content.rfind('-');
1177 ASSERT_NE(std::string::npos, index);
1178 content = content.substr(0, index);
1179 StatsReport::Id id(StatsReport::NewComponentId(content, 1));
1180 ASSERT_EQ(transport_id, id->ToString());
1181 const StatsReport* transport_report = FindReportById(reports, id);
1182 ASSERT_TRUE(transport_report);
1183 }
1184
1185 // This test verifies that a remote stats object will not be created for
1186 // an outgoing SSRC where remote stats are not returned.
TEST_P(StatsCollectorTrackTest,RemoteSsrcInfoIsAbsent)1187 TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsAbsent) {
1188 auto pc = CreatePeerConnection();
1189 auto stats = CreateStatsCollector(pc.get());
1190
1191 pc->AddVideoChannel("video", "transport");
1192 AddOutgoingVideoTrack(pc.get(), stats.get());
1193
1194 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1195 StatsReports reports;
1196 stats->GetStats(nullptr, &reports);
1197
1198 const StatsReport* remote_report =
1199 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1200 EXPECT_FALSE(remote_report);
1201 }
1202
1203 // This test verifies that a remote stats object will be created for
1204 // an outgoing SSRC where stats are returned.
TEST_P(StatsCollectorTrackTest,RemoteSsrcInfoIsPresent)1205 TEST_P(StatsCollectorTrackTest, RemoteSsrcInfoIsPresent) {
1206 auto pc = CreatePeerConnection();
1207 auto stats = CreateStatsCollector(pc.get());
1208
1209 SsrcReceiverInfo remote_ssrc_stats;
1210 remote_ssrc_stats.timestamp = 12345.678;
1211 remote_ssrc_stats.ssrc = kSsrcOfTrack;
1212 VideoSenderInfo video_sender_info;
1213 video_sender_info.add_ssrc(kSsrcOfTrack);
1214 video_sender_info.remote_stats.push_back(remote_ssrc_stats);
1215 VideoMediaInfo video_info;
1216 video_info.aggregated_senders.push_back(video_sender_info);
1217
1218 pc->AddVideoChannel("video", "transport", video_info);
1219
1220 AddOutgoingVideoTrack(pc.get(), stats.get());
1221
1222 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1223 StatsReports reports;
1224 stats->GetStats(nullptr, &reports);
1225
1226 const StatsReport* remote_report =
1227 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1228 ASSERT_TRUE(remote_report);
1229 EXPECT_EQ(12345.678, remote_report->timestamp());
1230 }
1231
1232 // This test verifies that the empty track report exists in the returned stats
1233 // when StatsCollector::UpdateStats is called with ssrc stats.
TEST_P(StatsCollectorTrackTest,ReportsFromRemoteTrack)1234 TEST_P(StatsCollectorTrackTest, ReportsFromRemoteTrack) {
1235 constexpr int64_t kNumOfPacketsConcealed = 54321;
1236
1237 auto pc = CreatePeerConnection();
1238 auto stats = CreateStatsCollector(pc.get());
1239
1240 VideoReceiverInfo video_receiver_info;
1241 video_receiver_info.add_ssrc(1234);
1242 video_receiver_info.packets_concealed = kNumOfPacketsConcealed;
1243 VideoMediaInfo video_info;
1244 video_info.receivers.push_back(video_receiver_info);
1245
1246 pc->AddVideoChannel("video", "transport", video_info);
1247
1248 AddIncomingVideoTrack(pc.get(), stats.get());
1249
1250 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1251 StatsReports reports;
1252 stats->GetStats(nullptr, &reports);
1253
1254 // `reports` should contain at least one session report, one track report,
1255 // and one ssrc report.
1256 EXPECT_LE(3u, reports.size());
1257 const StatsReport* track_report =
1258 FindNthReportByType(reports, StatsReport::kStatsReportTypeTrack, 1);
1259 ASSERT_TRUE(track_report);
1260 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1261
1262 std::string ssrc_id =
1263 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1264 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1265
1266 std::string track_id =
1267 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1268 EXPECT_EQ(kRemoteTrackId, track_id);
1269 }
1270
1271 // This test verifies the Ice Candidate report should contain the correct
1272 // information from local/remote candidates.
TEST_F(LegacyStatsCollectorTest,IceCandidateReport)1273 TEST_F(LegacyStatsCollectorTest, IceCandidateReport) {
1274 const std::string kTransportName = "transport";
1275 const rtc::AdapterType kNetworkType = rtc::ADAPTER_TYPE_ETHERNET;
1276 constexpr uint32_t kPriority = 1000;
1277
1278 constexpr int kLocalPort = 2000;
1279 const std::string kLocalIp = "192.168.0.1";
1280 const rtc::SocketAddress kLocalAddress(kLocalIp, kLocalPort);
1281
1282 constexpr int kRemotePort = 2001;
1283 const std::string kRemoteIp = "192.168.0.2";
1284 const rtc::SocketAddress kRemoteAddress(kRemoteIp, kRemotePort);
1285
1286 auto pc = CreatePeerConnection();
1287 auto stats = CreateStatsCollector(pc.get());
1288
1289 cricket::Candidate local;
1290 EXPECT_GT(local.id().length(), 0u);
1291 local.set_type(cricket::LOCAL_PORT_TYPE);
1292 local.set_protocol(cricket::UDP_PROTOCOL_NAME);
1293 local.set_address(kLocalAddress);
1294 local.set_priority(kPriority);
1295 local.set_network_type(kNetworkType);
1296
1297 cricket::Candidate remote;
1298 EXPECT_GT(remote.id().length(), 0u);
1299 remote.set_type(cricket::PRFLX_PORT_TYPE);
1300 remote.set_protocol(cricket::UDP_PROTOCOL_NAME);
1301 remote.set_address(kRemoteAddress);
1302 remote.set_priority(kPriority);
1303 remote.set_network_type(kNetworkType);
1304
1305 ConnectionInfo connection_info;
1306 connection_info.local_candidate = local;
1307 connection_info.remote_candidate = remote;
1308 TransportChannelStats channel_stats;
1309 channel_stats.ice_transport_stats.connection_infos.push_back(connection_info);
1310
1311 pc->AddVoiceChannel("audio", kTransportName);
1312 pc->SetTransportStats(kTransportName, channel_stats);
1313
1314 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1315 StatsReports reports;
1316 stats->GetStats(nullptr, &reports);
1317
1318 // Verify the local candidate report is populated correctly.
1319 EXPECT_EQ(
1320 "Cand-" + local.id(),
1321 ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1322 StatsReport::kStatsValueNameLocalCandidateId));
1323 EXPECT_EQ(
1324 kLocalIp,
1325 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1326 StatsReport::kStatsValueNameCandidateIPAddress));
1327 EXPECT_EQ(
1328 rtc::ToString(kLocalPort),
1329 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1330 StatsReport::kStatsValueNameCandidatePortNumber));
1331 EXPECT_EQ(
1332 cricket::UDP_PROTOCOL_NAME,
1333 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1334 StatsReport::kStatsValueNameCandidateTransportType));
1335 EXPECT_EQ(
1336 rtc::ToString(kPriority),
1337 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1338 StatsReport::kStatsValueNameCandidatePriority));
1339 EXPECT_EQ(
1340 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE),
1341 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1342 StatsReport::kStatsValueNameCandidateType));
1343 EXPECT_EQ(
1344 AdapterTypeToStatsType(kNetworkType),
1345 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports,
1346 StatsReport::kStatsValueNameCandidateNetworkType));
1347
1348 // Verify the remote candidate report is populated correctly.
1349 EXPECT_EQ(
1350 "Cand-" + remote.id(),
1351 ExtractStatsValue(StatsReport::kStatsReportTypeCandidatePair, reports,
1352 StatsReport::kStatsValueNameRemoteCandidateId));
1353 EXPECT_EQ(kRemoteIp,
1354 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1355 reports,
1356 StatsReport::kStatsValueNameCandidateIPAddress));
1357 EXPECT_EQ(rtc::ToString(kRemotePort),
1358 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1359 reports,
1360 StatsReport::kStatsValueNameCandidatePortNumber));
1361 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME,
1362 ExtractStatsValue(
1363 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1364 StatsReport::kStatsValueNameCandidateTransportType));
1365 EXPECT_EQ(rtc::ToString(kPriority),
1366 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1367 reports,
1368 StatsReport::kStatsValueNameCandidatePriority));
1369 EXPECT_EQ(
1370 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE),
1371 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate,
1372 reports, StatsReport::kStatsValueNameCandidateType));
1373 EXPECT_EQ(kNotFound,
1374 ExtractStatsValue(
1375 StatsReport::kStatsReportTypeIceRemoteCandidate, reports,
1376 StatsReport::kStatsValueNameCandidateNetworkType));
1377 }
1378
1379 // This test verifies that all chained certificates are correctly
1380 // reported
TEST_F(LegacyStatsCollectorTest,ChainedCertificateReportsCreated)1381 TEST_F(LegacyStatsCollectorTest, ChainedCertificateReportsCreated) {
1382 // Build local certificate chain.
1383 std::vector<std::string> local_ders(5);
1384 local_ders[0] = "These";
1385 local_ders[1] = "are";
1386 local_ders[2] = "some";
1387 local_ders[3] = "der";
1388 local_ders[4] = "values";
1389 rtc::FakeSSLIdentity local_identity(DersToPems(local_ders));
1390
1391 // Build remote certificate chain
1392 std::vector<std::string> remote_ders(4);
1393 remote_ders[0] = "A";
1394 remote_ders[1] = "non-";
1395 remote_ders[2] = "intersecting";
1396 remote_ders[3] = "set";
1397 rtc::FakeSSLIdentity remote_identity(DersToPems(remote_ders));
1398
1399 TestCertificateReports(local_identity, local_ders, remote_identity,
1400 remote_ders);
1401 }
1402
1403 // This test verifies that all certificates without chains are correctly
1404 // reported.
TEST_F(LegacyStatsCollectorTest,ChainlessCertificateReportsCreated)1405 TEST_F(LegacyStatsCollectorTest, ChainlessCertificateReportsCreated) {
1406 // Build local certificate.
1407 std::string local_der = "This is the local der.";
1408 rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
1409
1410 // Build remote certificate.
1411 std::string remote_der = "This is somebody else's der.";
1412 rtc::FakeSSLIdentity remote_identity(DerToPem(remote_der));
1413
1414 TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1415 remote_identity,
1416 std::vector<std::string>(1, remote_der));
1417 }
1418
1419 // This test verifies that the stats are generated correctly when no
1420 // transport is present.
TEST_F(LegacyStatsCollectorTest,NoTransport)1421 TEST_F(LegacyStatsCollectorTest, NoTransport) {
1422 auto pc = CreatePeerConnection();
1423 auto stats = CreateStatsCollector(pc.get());
1424
1425 // This will cause the fake PeerConnection to generate a TransportStats entry
1426 // but with only a single dummy TransportChannelStats.
1427 pc->AddVoiceChannel("audio", "transport");
1428
1429 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1430 StatsReports reports;
1431 stats->GetStats(nullptr, &reports);
1432
1433 // Check that the local certificate is absent.
1434 std::string local_certificate_id =
1435 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1436 StatsReport::kStatsValueNameLocalCertificateId);
1437 ASSERT_EQ(kNotFound, local_certificate_id);
1438
1439 // Check that the remote certificate is absent.
1440 std::string remote_certificate_id =
1441 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1442 StatsReport::kStatsValueNameRemoteCertificateId);
1443 ASSERT_EQ(kNotFound, remote_certificate_id);
1444
1445 // Check that the negotiated ciphers are absent.
1446 std::string dtls_cipher_suite =
1447 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1448 StatsReport::kStatsValueNameDtlsCipher);
1449 ASSERT_EQ(kNotFound, dtls_cipher_suite);
1450 std::string srtp_crypto_suite =
1451 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports,
1452 StatsReport::kStatsValueNameSrtpCipher);
1453 ASSERT_EQ(kNotFound, srtp_crypto_suite);
1454 }
1455
1456 // This test verifies that a remote certificate with an unsupported digest
1457 // algorithm is correctly ignored.
TEST_F(LegacyStatsCollectorTest,UnsupportedDigestIgnored)1458 TEST_F(LegacyStatsCollectorTest, UnsupportedDigestIgnored) {
1459 // Build a local certificate.
1460 std::string local_der = "This is the local der.";
1461 rtc::FakeSSLIdentity local_identity(DerToPem(local_der));
1462
1463 // Build a remote certificate with an unsupported digest algorithm.
1464 std::string remote_der = "This is somebody else's der.";
1465 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der));
1466 remote_cert.set_digest_algorithm("foobar");
1467 rtc::FakeSSLIdentity remote_identity(remote_cert);
1468
1469 TestCertificateReports(local_identity, std::vector<std::string>(1, local_der),
1470 remote_identity, std::vector<std::string>());
1471 }
1472
1473 // This test verifies that the audio/video related stats which are -1 initially
1474 // will be filtered out.
TEST_P(StatsCollectorTrackTest,FilterOutNegativeInitialValues)1475 TEST_P(StatsCollectorTrackTest, FilterOutNegativeInitialValues) {
1476 // This test uses streams, but only works for the stream case.
1477 if (!GetParam()) {
1478 return;
1479 }
1480
1481 auto pc = CreatePeerConnection();
1482 auto stats = CreateStatsCollector(pc.get());
1483
1484 // Create a local stream with a local audio track and adds it to the stats.
1485 stream_ = MediaStream::Create("streamid");
1486 auto local_track =
1487 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
1488 stream_->AddTrack(rtc::scoped_refptr<AudioTrackInterface>(local_track.get()));
1489 pc->AddSender(CreateMockSender(local_track, kSsrcOfTrack));
1490 if (GetParam()) {
1491 stats->AddStream(stream_.get());
1492 }
1493 stats->AddLocalAudioTrack(local_track.get(), kSsrcOfTrack);
1494
1495 // Create a remote stream with a remote audio track and adds it to the stats.
1496 rtc::scoped_refptr<MediaStream> remote_stream(
1497 MediaStream::Create("remotestreamid"));
1498 rtc::scoped_refptr<AudioTrackInterface> remote_track =
1499 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kRemoteTrackId);
1500 remote_stream->AddTrack(remote_track);
1501 pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
1502 if (GetParam()) {
1503 stats->AddStream(remote_stream.get());
1504 }
1505
1506 VoiceSenderInfo voice_sender_info;
1507 voice_sender_info.add_ssrc(kSsrcOfTrack);
1508 // These values are set to -1 initially in audio_send_stream.
1509 // The voice_sender_info will read the values from audio_send_stream.
1510 voice_sender_info.rtt_ms = -1;
1511 voice_sender_info.packets_lost = -1;
1512 voice_sender_info.jitter_ms = -1;
1513
1514 // Some of the contents in `voice_sender_info` needs to be updated from the
1515 // `audio_track_`.
1516 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &voice_sender_info,
1517 true);
1518
1519 VoiceReceiverInfo voice_receiver_info;
1520 voice_receiver_info.add_ssrc(kSsrcOfTrack);
1521 voice_receiver_info.capture_start_ntp_time_ms = -1;
1522 voice_receiver_info.audio_level = -1;
1523
1524 // Constructs an ssrc stats update.
1525 VoiceMediaInfo voice_info;
1526 voice_info.senders.push_back(voice_sender_info);
1527 voice_info.receivers.push_back(voice_receiver_info);
1528
1529 auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1530 voice_media_channel->SetStats(voice_info);
1531
1532 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1533
1534 // Get stats for the local track.
1535 StatsReports reports;
1536 stats->GetStats(local_track.get(), &reports);
1537 const StatsReport* report =
1538 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1539 ASSERT_TRUE(report);
1540 // The -1 will not be added to the stats report.
1541 std::string value_in_report;
1542 EXPECT_FALSE(
1543 GetValue(report, StatsReport::kStatsValueNameRtt, &value_in_report));
1544 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNamePacketsLost,
1545 &value_in_report));
1546 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameJitterReceived,
1547 &value_in_report));
1548 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayMedian,
1549 &value_in_report));
1550 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameEchoDelayStdDev,
1551 &value_in_report));
1552
1553 // Get stats for the remote track.
1554 reports.clear();
1555 stats->GetStats(remote_track.get(), &reports);
1556 report = FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1557 ASSERT_TRUE(report);
1558 EXPECT_FALSE(GetValue(report,
1559 StatsReport::kStatsValueNameCaptureStartNtpTimeMs,
1560 &value_in_report));
1561 EXPECT_FALSE(GetValue(report, StatsReport::kStatsValueNameAudioInputLevel,
1562 &value_in_report));
1563 }
1564
1565 // This test verifies that a local stats object can get statistics via
1566 // AudioTrackInterface::GetStats() method.
TEST_P(StatsCollectorTrackTest,GetStatsFromLocalAudioTrack)1567 TEST_P(StatsCollectorTrackTest, GetStatsFromLocalAudioTrack) {
1568 auto pc = CreatePeerConnection();
1569 auto stats = CreateStatsCollector(pc.get());
1570
1571 AddOutgoingAudioTrack(pc.get(), stats.get());
1572 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1573
1574 VoiceSenderInfo voice_sender_info;
1575 InitVoiceSenderInfo(&voice_sender_info);
1576 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1577 false);
1578 VoiceMediaInfo voice_info;
1579 voice_info.senders.push_back(voice_sender_info);
1580
1581 auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1582 voice_media_channel->SetStats(voice_info);
1583
1584 StatsReports reports; // returned values.
1585 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1586
1587 // Verify that there is no remote report for the local audio track because
1588 // we did not set it up.
1589 const StatsReport* remote_report =
1590 FindNthReportByType(reports, StatsReport::kStatsReportTypeRemoteSsrc, 1);
1591 EXPECT_TRUE(remote_report == NULL);
1592 }
1593
1594 // This test verifies that audio receive streams populate stats reports
1595 // correctly.
TEST_P(StatsCollectorTrackTest,GetStatsFromRemoteStream)1596 TEST_P(StatsCollectorTrackTest, GetStatsFromRemoteStream) {
1597 auto pc = CreatePeerConnection();
1598 auto stats = CreateStatsCollector(pc.get());
1599
1600 AddIncomingAudioTrack(pc.get(), stats.get());
1601
1602 VoiceReceiverInfo voice_receiver_info;
1603 InitVoiceReceiverInfo(&voice_receiver_info);
1604 voice_receiver_info.codec_name = "fake_codec";
1605 VoiceMediaInfo voice_info;
1606 voice_info.receivers.push_back(voice_receiver_info);
1607
1608 auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1609 voice_media_channel->SetStats(voice_info);
1610
1611 StatsReports reports; // returned values.
1612 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1613 }
1614
1615 // This test verifies that a local stats object won't update its statistics
1616 // after a RemoveLocalAudioTrack() call.
TEST_P(StatsCollectorTrackTest,GetStatsAfterRemoveAudioStream)1617 TEST_P(StatsCollectorTrackTest, GetStatsAfterRemoveAudioStream) {
1618 auto pc = CreatePeerConnection();
1619 auto stats = CreateStatsCollector(pc.get());
1620
1621 AddOutgoingAudioTrack(pc.get(), stats.get());
1622 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1623
1624 VoiceSenderInfo voice_sender_info;
1625 InitVoiceSenderInfo(&voice_sender_info);
1626 VoiceMediaInfo voice_info;
1627 voice_info.senders.push_back(voice_sender_info);
1628
1629 auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1630 voice_media_channel->SetStats(voice_info);
1631
1632 stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1633
1634 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1635 StatsReports reports;
1636 stats->GetStats(nullptr, &reports);
1637
1638 // The report will exist since we don't remove them in RemoveStream().
1639 const StatsReport* report =
1640 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1641 ASSERT_TRUE(report);
1642 EXPECT_EQ(stats->GetTimeNow(), report->timestamp());
1643 std::string track_id =
1644 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1645 EXPECT_EQ(kLocalTrackId, track_id);
1646 std::string ssrc_id =
1647 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameSsrc);
1648 EXPECT_EQ(rtc::ToString(kSsrcOfTrack), ssrc_id);
1649
1650 // Verifies the values in the track report, no value will be changed by the
1651 // AudioTrackInterface::GetSignalValue() and
1652 // AudioProcessorInterface::GetStats();
1653 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1654 }
1655
1656 // This test verifies that when ongoing and incoming audio tracks are using
1657 // the same ssrc, they populate stats reports correctly.
TEST_P(StatsCollectorTrackTest,LocalAndRemoteTracksWithSameSsrc)1658 TEST_P(StatsCollectorTrackTest, LocalAndRemoteTracksWithSameSsrc) {
1659 auto pc = CreatePeerConnection();
1660 auto stats = CreateStatsCollector(pc.get());
1661
1662 // Create a local stream with a local audio track and adds it to the stats.
1663 AddOutgoingAudioTrack(pc.get(), stats.get());
1664 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1665
1666 // Create a remote stream with a remote audio track and adds it to the stats.
1667 rtc::scoped_refptr<MediaStream> remote_stream(
1668 MediaStream::Create("remotestreamid"));
1669 rtc::scoped_refptr<AudioTrackInterface> remote_track =
1670 rtc::make_ref_counted<FakeAudioTrack>(kRemoteTrackId);
1671 pc->AddReceiver(CreateMockReceiver(remote_track, kSsrcOfTrack));
1672 remote_stream->AddTrack(remote_track);
1673 stats->AddStream(remote_stream.get());
1674
1675 VoiceSenderInfo voice_sender_info;
1676 InitVoiceSenderInfo(&voice_sender_info);
1677 // Some of the contents in `voice_sender_info` needs to be updated from the
1678 // `audio_track_`.
1679 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1680 true);
1681
1682 VoiceReceiverInfo voice_receiver_info;
1683 InitVoiceReceiverInfo(&voice_receiver_info);
1684
1685 // Constructs an ssrc stats update.
1686 VoiceMediaInfo voice_info;
1687 voice_info.senders.push_back(voice_sender_info);
1688 voice_info.receivers.push_back(voice_receiver_info);
1689
1690 // Instruct the session to return stats containing the transport channel.
1691 auto* voice_media_channel = pc->AddVoiceChannel("audio", "transport");
1692 voice_media_channel->SetStats(voice_info);
1693
1694 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1695
1696 // Get stats for the local track.
1697 StatsReports reports; // returned values.
1698 stats->GetStats(audio_track_.get(), &reports);
1699
1700 const StatsReport* track_report =
1701 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1702 ASSERT_TRUE(track_report);
1703 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1704 std::string track_id =
1705 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1706 EXPECT_EQ(kLocalTrackId, track_id);
1707 VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
1708
1709 // Get stats for the remote track.
1710 reports.clear();
1711 stats->GetStats(remote_track.get(), &reports);
1712 track_report =
1713 FindNthReportByType(reports, StatsReport::kStatsReportTypeSsrc, 1);
1714 ASSERT_TRUE(track_report);
1715 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp());
1716 track_id =
1717 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameTrackId);
1718 EXPECT_EQ(kRemoteTrackId, track_id);
1719 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info);
1720 }
1721
1722 // This test verifies that when two outgoing audio tracks are using the same
1723 // ssrc at different times, they populate stats reports correctly.
1724 // TODO(xians): Figure out if it is possible to encapsulate the setup and
1725 // avoid duplication of code in test cases.
TEST_P(StatsCollectorTrackTest,TwoLocalTracksWithSameSsrc)1726 TEST_P(StatsCollectorTrackTest, TwoLocalTracksWithSameSsrc) {
1727 // This test only makes sense when we're using streams.
1728 if (!GetParam()) {
1729 return;
1730 }
1731
1732 auto pc = CreatePeerConnection();
1733 auto stats = CreateStatsCollector(pc.get());
1734
1735 // Create a local stream with a local audio track and adds it to the stats.
1736 auto sender = AddOutgoingAudioTrack(pc.get(), stats.get());
1737 stats->AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1738
1739 VoiceSenderInfo voice_sender_info;
1740 InitVoiceSenderInfo(&voice_sender_info);
1741 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info,
1742 false);
1743 voice_sender_info.add_ssrc(kSsrcOfTrack);
1744 VoiceMediaInfo voice_info;
1745 voice_info.senders.push_back(voice_sender_info);
1746
1747 auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1748 voice_media_channel->SetStats(voice_info);
1749
1750 StatsReports reports; // returned values.
1751 VerifyAudioTrackStats(audio_track_.get(), stats.get(), voice_info, &reports);
1752
1753 // Remove the previous audio track from the stream.
1754 stream_->RemoveTrack(audio_track());
1755 stats->RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1756 pc->RemoveSender(sender);
1757
1758 // Create a new audio track and adds it to the stream and stats.
1759 static const std::string kNewTrackId = "new_track_id";
1760 auto new_audio_track = rtc::make_ref_counted<FakeAudioTrack>(kNewTrackId);
1761 pc->AddSender(CreateMockSender(new_audio_track, kSsrcOfTrack));
1762 stream_->AddTrack(
1763 rtc::scoped_refptr<AudioTrackInterface>(new_audio_track.get()));
1764
1765 stats->AddLocalAudioTrack(new_audio_track.get(), kSsrcOfTrack);
1766 stats->InvalidateCache();
1767
1768 VoiceSenderInfo new_voice_sender_info;
1769 InitVoiceSenderInfo(&new_voice_sender_info);
1770 UpdateVoiceSenderInfoFromAudioTrack(new_audio_track.get(),
1771 &new_voice_sender_info, false);
1772 VoiceMediaInfo new_voice_info;
1773 new_voice_info.senders.push_back(new_voice_sender_info);
1774 voice_media_channel->SetStats(new_voice_info);
1775
1776 reports.clear();
1777 VerifyAudioTrackStats(new_audio_track.get(), stats.get(), new_voice_info,
1778 &reports);
1779 }
1780
1781 // Test that if there are two local senders with the same track then two SSRC
1782 // reports will be created, one for each sender, with the same track ID and one
1783 // track report will be created for the shared track.
TEST_P(StatsCollectorTrackTest,TwoLocalSendersWithSameTrack)1784 TEST_P(StatsCollectorTrackTest, TwoLocalSendersWithSameTrack) {
1785 constexpr uint32_t kFirstSsrc = 22;
1786 constexpr uint32_t kSecondSsrc = 33;
1787
1788 auto pc = CreatePeerConnection();
1789 auto stats = CreateStatsCollector(pc.get());
1790
1791 auto local_track =
1792 rtc::make_ref_counted<FakeAudioTrackWithInitValue>(kLocalTrackId);
1793 pc->AddSender(CreateMockSender(local_track, kFirstSsrc));
1794 stats->AddLocalAudioTrack(local_track.get(), kFirstSsrc);
1795 pc->AddSender(CreateMockSender(local_track, kSecondSsrc));
1796 stats->AddLocalAudioTrack(local_track.get(), kSecondSsrc);
1797
1798 VoiceSenderInfo first_sender_info;
1799 InitVoiceSenderInfo(&first_sender_info, kFirstSsrc);
1800 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &first_sender_info,
1801 false);
1802
1803 VoiceSenderInfo second_sender_info;
1804 InitVoiceSenderInfo(&second_sender_info, kSecondSsrc);
1805 UpdateVoiceSenderInfoFromAudioTrack(local_track.get(), &second_sender_info,
1806 false);
1807
1808 VoiceMediaInfo voice_info;
1809 voice_info.senders.push_back(first_sender_info);
1810 voice_info.senders.push_back(second_sender_info);
1811
1812 auto* voice_media_channel = pc->AddVoiceChannel("voice", "transport");
1813 voice_media_channel->SetStats(voice_info);
1814
1815 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1816
1817 StatsReports reports;
1818 stats->GetStats(local_track.get(), &reports);
1819
1820 // Both SSRC reports have the same track ID.
1821 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1822 reports, StatsReport::kStatsReportTypeSsrc,
1823 StatsReport::kStatsValueNameTrackId, 1));
1824 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1825 reports, StatsReport::kStatsReportTypeSsrc,
1826 StatsReport::kStatsValueNameTrackId, 2));
1827
1828 // The SSRC in each SSRC report is different and correspond to the sender
1829 // SSRC.
1830 std::vector<absl::optional<std::string>> ssrcs = {
1831 GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1832 StatsReport::kStatsValueNameSsrc, 1),
1833 GetValueInNthReportByType(reports, StatsReport::kStatsReportTypeSsrc,
1834 StatsReport::kStatsValueNameSsrc, 2)};
1835 EXPECT_THAT(ssrcs, UnorderedElementsAre(rtc::ToString(kFirstSsrc),
1836 rtc::ToString(kSecondSsrc)));
1837
1838 // There is one track report with the same track ID as the SSRC reports.
1839 EXPECT_EQ(
1840 1u, GetReportsByType(reports, StatsReport::kStatsReportTypeTrack).size());
1841 EXPECT_EQ(kLocalTrackId, GetValueInNthReportByType(
1842 reports, StatsReport::kStatsReportTypeTrack,
1843 StatsReport::kStatsValueNameTrackId, 1));
1844 }
1845
1846 // This test verifies that stats are correctly set in video send ssrc stats.
TEST_P(StatsCollectorTrackTest,VerifyVideoSendSsrcStats)1847 TEST_P(StatsCollectorTrackTest, VerifyVideoSendSsrcStats) {
1848 auto pc = CreatePeerConnection();
1849 auto stats = CreateStatsCollector(pc.get());
1850
1851 AddOutgoingVideoTrack(pc.get(), stats.get());
1852
1853 VideoSenderInfo video_sender_info;
1854 video_sender_info.add_ssrc(1234);
1855 video_sender_info.frames_encoded = 10;
1856 video_sender_info.qp_sum = 11;
1857 VideoMediaInfo video_info;
1858 video_info.aggregated_senders.push_back(video_sender_info);
1859
1860 pc->AddVideoChannel("video", "transport", video_info);
1861
1862 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1863 StatsReports reports;
1864 stats->GetStats(nullptr, &reports);
1865
1866 EXPECT_EQ(rtc::ToString(video_sender_info.frames_encoded),
1867 ExtractSsrcStatsValue(reports,
1868 StatsReport::kStatsValueNameFramesEncoded));
1869 EXPECT_EQ(rtc::ToString(*video_sender_info.qp_sum),
1870 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
1871 }
1872
1873 // This test verifies that stats are correctly set in video receive ssrc stats.
TEST_P(StatsCollectorTrackTest,VerifyVideoReceiveSsrcStatsNew)1874 TEST_P(StatsCollectorTrackTest, VerifyVideoReceiveSsrcStatsNew) {
1875 auto pc = CreatePeerConnection();
1876 auto stats = CreateStatsCollector(pc.get());
1877
1878 AddIncomingVideoTrack(pc.get(), stats.get());
1879
1880 VideoReceiverInfo video_receiver_info;
1881 video_receiver_info.add_ssrc(1234);
1882 video_receiver_info.frames_decoded = 10;
1883 video_receiver_info.qp_sum = 11;
1884 VideoMediaInfo video_info;
1885 video_info.receivers.push_back(video_receiver_info);
1886
1887 pc->AddVideoChannel("video", "transport", video_info);
1888
1889 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1890 StatsReports reports;
1891 stats->GetStats(nullptr, &reports);
1892
1893 EXPECT_EQ(rtc::ToString(video_receiver_info.frames_decoded),
1894 ExtractSsrcStatsValue(reports,
1895 StatsReport::kStatsValueNameFramesDecoded));
1896 EXPECT_EQ(rtc::ToString(*video_receiver_info.qp_sum),
1897 ExtractSsrcStatsValue(reports, StatsReport::kStatsValueNameQpSum));
1898 }
1899
1900 INSTANTIATE_TEST_SUITE_P(HasStream, StatsCollectorTrackTest, ::testing::Bool());
1901
1902 } // namespace webrtc
1903