blob: 24be20af165266b52621ffc78f5fcbcf44885ad8 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <stdio.h>
28
29#include "talk/app/webrtc/statscollector.h"
30
31#include "talk/app/webrtc/mediastream.h"
henrike@webrtc.org40b3b682014-03-03 18:30:11 +000032#include "talk/app/webrtc/mediastreaminterface.h"
33#include "talk/app/webrtc/mediastreamtrack.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034#include "talk/app/webrtc/videotrack.h"
wu@webrtc.org4551b792013-10-09 15:37:36 +000035#include "talk/base/base64.h"
36#include "talk/base/fakesslidentity.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/base/gunit.h"
38#include "talk/media/base/fakemediaengine.h"
39#include "talk/media/devices/fakedevicemanager.h"
40#include "talk/p2p/base/fakesession.h"
41#include "talk/session/media/channelmanager.h"
42#include "testing/base/public/gmock.h"
43
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000044using cricket::StatsOptions;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045using testing::_;
46using testing::DoAll;
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000047using testing::Field;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048using testing::Return;
49using testing::ReturnNull;
50using testing::SetArgPointee;
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000051using webrtc::PeerConnectionInterface;
henrike@webrtc.org40b3b682014-03-03 18:30:11 +000052using webrtc::StatsReport;
53using webrtc::StatsReports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054
55namespace cricket {
56
57class ChannelManager;
58class FakeDeviceManager;
59
60} // namespace cricket
61
62namespace {
63
64// Error return values
65const char kNotFound[] = "NOT FOUND";
66const char kNoReports[] = "NO REPORTS";
67
wu@webrtc.org97077a32013-10-25 21:18:33 +000068// Constant names for track identification.
69const char kTrackId[] = "somename";
henrike@webrtc.org40b3b682014-03-03 18:30:11 +000070const char kAudioTrackId[] = "audio_track_id";
wu@webrtc.org97077a32013-10-25 21:18:33 +000071const uint32 kSsrcOfTrack = 1234;
72
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073class MockWebRtcSession : public webrtc::WebRtcSession {
74 public:
75 explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
76 : WebRtcSession(channel_manager, talk_base::Thread::Current(),
wu@webrtc.org4551b792013-10-09 15:37:36 +000077 talk_base::Thread::Current(), NULL, NULL) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078 }
henrike@webrtc.org40b3b682014-03-03 18:30:11 +000079 MOCK_METHOD0(voice_channel, cricket::VoiceChannel*());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080 MOCK_METHOD0(video_channel, cricket::VideoChannel*());
81 MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
82 MOCK_METHOD1(GetStats, bool(cricket::SessionStats*));
wu@webrtc.org4551b792013-10-09 15:37:36 +000083 MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084};
85
86class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
87 public:
88 MockVideoMediaChannel()
89 : cricket::FakeVideoMediaChannel(NULL) {
90 }
91 // MOCK_METHOD0(transport_channel, cricket::TransportChannel*());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +000092 MOCK_METHOD2(GetStats, bool(const StatsOptions&, cricket::VideoMediaInfo*));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000093};
94
henrike@webrtc.org40b3b682014-03-03 18:30:11 +000095class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel {
96 public:
97 MockVoiceMediaChannel() : cricket::FakeVoiceMediaChannel(NULL) {
98 }
99 MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*));
100};
101
102class FakeAudioProcessor : public webrtc::AudioProcessorInterface {
103 public:
104 FakeAudioProcessor() {}
105 ~FakeAudioProcessor() {}
106
107 private:
108 virtual void GetStats(
109 AudioProcessorInterface::AudioProcessorStats* stats) OVERRIDE {
110 stats->typing_noise_detected = true;
111 stats->echo_return_loss = 2;
112 stats->echo_return_loss_enhancement = 3;
113 stats->echo_delay_median_ms = 4;
114 stats->aec_quality_min = 5.1f;
115 stats->echo_delay_std_ms = 6;
116 }
117};
118
119class FakeLocalAudioTrack
120 : public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface> {
121 public:
122 explicit FakeLocalAudioTrack(const std::string& id)
123 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id),
124 processor_(new talk_base::RefCountedObject<FakeAudioProcessor>()) {}
125 std::string kind() const OVERRIDE {
126 return "audio";
127 }
128 virtual webrtc::AudioSourceInterface* GetSource() const OVERRIDE {
129 return NULL;
130 }
131 virtual void AddSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {}
132 virtual void RemoveSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE {}
133 virtual bool GetSignalLevel(int* level) OVERRIDE {
134 *level = 1;
135 return true;
136 }
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000137 virtual talk_base::scoped_refptr<webrtc::AudioProcessorInterface>
138 GetAudioProcessor() OVERRIDE {
139 return processor_;
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000140 }
141
142 private:
143 talk_base::scoped_refptr<FakeAudioProcessor> processor_;
144};
145
146bool GetValue(const StatsReport* report,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000147 const std::string& name,
148 std::string* value) {
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000149 StatsReport::Values::const_iterator it = report->values.begin();
wu@webrtc.org4551b792013-10-09 15:37:36 +0000150 for (; it != report->values.end(); ++it) {
151 if (it->name == name) {
152 *value = it->value;
153 return true;
154 }
155 }
156 return false;
157}
158
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159std::string ExtractStatsValue(const std::string& type,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000160 const StatsReports& reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161 const std::string name) {
162 if (reports.empty()) {
163 return kNoReports;
164 }
165 for (size_t i = 0; i < reports.size(); ++i) {
166 if (reports[i].type != type)
167 continue;
wu@webrtc.org4551b792013-10-09 15:37:36 +0000168 std::string ret;
169 if (GetValue(&reports[i], name, &ret)) {
170 return ret;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171 }
172 }
173
174 return kNotFound;
175}
176
177// Finds the |n|-th report of type |type| in |reports|.
178// |n| starts from 1 for finding the first report.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000179const StatsReport* FindNthReportByType(
180 const StatsReports& reports, const std::string& type, int n) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181 for (size_t i = 0; i < reports.size(); ++i) {
182 if (reports[i].type == type) {
183 n--;
184 if (n == 0)
185 return &reports[i];
186 }
187 }
188 return NULL;
189}
190
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000191const StatsReport* FindReportById(const StatsReports& reports,
192 const std::string& id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193 for (size_t i = 0; i < reports.size(); ++i) {
194 if (reports[i].id == id) {
195 return &reports[i];
196 }
197 }
198 return NULL;
199}
200
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000201std::string ExtractSsrcStatsValue(StatsReports reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000202 const std::string& name) {
203 return ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000204 StatsReport::kStatsReportTypeSsrc, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000205}
206
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000207std::string ExtractBweStatsValue(StatsReports reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208 const std::string& name) {
209 return ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000210 StatsReport::kStatsReportTypeBwe, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000211}
212
wu@webrtc.org4551b792013-10-09 15:37:36 +0000213std::string DerToPem(const std::string& der) {
214 return talk_base::SSLIdentity::DerToPem(
215 talk_base::kPemTypeCertificate,
216 reinterpret_cast<const unsigned char*>(der.c_str()),
217 der.length());
218}
219
220std::vector<std::string> DersToPems(
221 const std::vector<std::string>& ders) {
222 std::vector<std::string> pems(ders.size());
223 std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem);
224 return pems;
225}
226
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000227void CheckCertChainReports(const StatsReports& reports,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000228 const std::vector<std::string>& ders,
229 const std::string& start_id) {
230 std::string certificate_id = start_id;
231 size_t i = 0;
232 while (true) {
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000233 const StatsReport* report = FindReportById(reports, certificate_id);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000234 ASSERT_TRUE(report != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000235
wu@webrtc.org4551b792013-10-09 15:37:36 +0000236 std::string der_base64;
237 EXPECT_TRUE(GetValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000238 report, StatsReport::kStatsValueNameDer, &der_base64));
wu@webrtc.org4551b792013-10-09 15:37:36 +0000239 std::string der = talk_base::Base64::Decode(der_base64,
240 talk_base::Base64::DO_STRICT);
241 EXPECT_EQ(ders[i], der);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000242
243 std::string fingerprint_algorithm;
244 EXPECT_TRUE(GetValue(
245 report,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000246 StatsReport::kStatsValueNameFingerprintAlgorithm,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000247 &fingerprint_algorithm));
248 // The digest algorithm for a FakeSSLCertificate is always SHA-1.
249 std::string sha_1_str = talk_base::DIGEST_SHA_1;
250 EXPECT_EQ(sha_1_str, fingerprint_algorithm);
251
252 std::string dummy_fingerprint; // Value is not checked.
253 EXPECT_TRUE(GetValue(
254 report,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000255 StatsReport::kStatsValueNameFingerprint,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000256 &dummy_fingerprint));
257
wu@webrtc.org4551b792013-10-09 15:37:36 +0000258 ++i;
259 if (!GetValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000260 report, StatsReport::kStatsValueNameIssuerId, &certificate_id))
wu@webrtc.org4551b792013-10-09 15:37:36 +0000261 break;
262 }
263 EXPECT_EQ(ders.size(), i);
264}
265
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000266void VerifyVoiceSenderInfoReport(const StatsReport* report,
267 const cricket::VoiceSenderInfo& sinfo) {
268 std::string value_in_report;
269 EXPECT_TRUE(GetValue(
270 report, StatsReport::kStatsValueNameCodecName, &value_in_report));
271 EXPECT_EQ(sinfo.codec_name, value_in_report);
272 EXPECT_TRUE(GetValue(
273 report, StatsReport::kStatsValueNameBytesSent, &value_in_report));
274 EXPECT_EQ(talk_base::ToString<int64>(sinfo.bytes_sent), value_in_report);
275 EXPECT_TRUE(GetValue(
276 report, StatsReport::kStatsValueNamePacketsSent, &value_in_report));
277 EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_sent), value_in_report);
278 EXPECT_TRUE(GetValue(
henrike@webrtc.orgffe26202014-03-19 22:20:10 +0000279 report, StatsReport::kStatsValueNamePacketsLost, &value_in_report));
280 EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_lost), value_in_report);
281 EXPECT_TRUE(GetValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000282 report, StatsReport::kStatsValueNameRtt, &value_in_report));
283 EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
284 EXPECT_TRUE(GetValue(
285 report, StatsReport::kStatsValueNameRtt, &value_in_report));
286 EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
287 EXPECT_TRUE(GetValue(
288 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report));
289 EXPECT_EQ(talk_base::ToString<int>(sinfo.jitter_ms), value_in_report);
290 EXPECT_TRUE(GetValue(
291 report, StatsReport::kStatsValueNameEchoCancellationQualityMin,
292 &value_in_report));
293 EXPECT_EQ(talk_base::ToString<float>(sinfo.aec_quality_min), value_in_report);
294 EXPECT_TRUE(GetValue(
295 report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report));
296 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_median_ms),
297 value_in_report);
298 EXPECT_TRUE(GetValue(
299 report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report));
300 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_std_ms),
301 value_in_report);
302 EXPECT_TRUE(GetValue(
303 report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report));
304 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss),
305 value_in_report);
306 EXPECT_TRUE(GetValue(
307 report, StatsReport::kStatsValueNameEchoReturnLossEnhancement,
308 &value_in_report));
309 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss_enhancement),
310 value_in_report);
311 EXPECT_TRUE(GetValue(
312 report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report));
313 EXPECT_EQ(talk_base::ToString<int>(sinfo.audio_level), value_in_report);
314 EXPECT_TRUE(GetValue(
315 report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report));
316 std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
317 EXPECT_EQ(typing_detected, value_in_report);
318}
319
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320class StatsCollectorTest : public testing::Test {
321 protected:
322 StatsCollectorTest()
323 : media_engine_(new cricket::FakeMediaEngine),
324 channel_manager_(
325 new cricket::ChannelManager(media_engine_,
326 new cricket::FakeDeviceManager(),
327 talk_base::Thread::Current())),
wu@webrtc.org97077a32013-10-25 21:18:33 +0000328 session_(channel_manager_.get()),
329 track_id_(kTrackId) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330 // By default, we ignore session GetStats calls.
331 EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
332 }
333
wu@webrtc.org97077a32013-10-25 21:18:33 +0000334 // This creates a standard setup with a transport called "trspname"
335 // having one transport channel
336 // and the specified virtual connection name.
337 void InitSessionStats(const std::string vc_name) {
338 const std::string kTransportName("trspname");
339 cricket::TransportStats transport_stats;
340 cricket::TransportChannelStats channel_stats;
341 channel_stats.component = 1;
342 transport_stats.content_name = kTransportName;
343 transport_stats.channel_stats.push_back(channel_stats);
344
345 session_stats_.transport_stats[kTransportName] = transport_stats;
346 session_stats_.proxy_to_transport[vc_name] = kTransportName;
347 }
348
349 // Adds a track with a given SSRC into the stats.
350 void AddVideoTrackStats() {
351 stream_ = webrtc::MediaStream::Create("streamlabel");
352 track_= webrtc::VideoTrack::Create(kTrackId, NULL);
353 stream_->AddTrack(track_);
354 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
355 .WillRepeatedly(DoAll(SetArgPointee<1>(track_id_),
356 Return(true)));
357 }
358
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000359 // Adds a local audio track with a given SSRC into the stats.
360 void AddLocalAudioTrackStats() {
361 if (stream_ == NULL)
362 stream_ = webrtc::MediaStream::Create("streamlabel");
363
364 audio_track_ =
365 new talk_base::RefCountedObject<FakeLocalAudioTrack>(kAudioTrackId);
366 stream_->AddTrack(audio_track_);
367 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
368 .WillRepeatedly(DoAll(SetArgPointee<1>(kAudioTrackId),
369 Return(true)));
370 }
371
wu@webrtc.org4551b792013-10-09 15:37:36 +0000372 void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
373 const std::vector<std::string>& local_ders,
374 const talk_base::FakeSSLCertificate& remote_cert,
375 const std::vector<std::string>& remote_ders) {
376 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000377 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000378 stats.set_session(&session_);
379
380 // Fake stats to process.
381 cricket::TransportChannelStats channel_stats;
382 channel_stats.component = 1;
383
384 cricket::TransportStats transport_stats;
385 transport_stats.content_name = "audio";
386 transport_stats.channel_stats.push_back(channel_stats);
387
388 cricket::SessionStats session_stats;
389 session_stats.transport_stats[transport_stats.content_name] =
390 transport_stats;
391
392 // Fake certificates to report.
393 talk_base::FakeSSLIdentity local_identity(local_cert);
394 talk_base::scoped_ptr<talk_base::FakeSSLCertificate> remote_cert_copy(
395 remote_cert.GetReference());
396
397 // Fake transport object.
398 talk_base::scoped_ptr<cricket::FakeTransport> transport(
399 new cricket::FakeTransport(
400 session_.signaling_thread(),
401 session_.worker_thread(),
402 transport_stats.content_name));
403 transport->SetIdentity(&local_identity);
404 cricket::FakeTransportChannel* channel =
405 static_cast<cricket::FakeTransportChannel*>(
406 transport->CreateChannel(channel_stats.component));
407 EXPECT_FALSE(channel == NULL);
408 channel->SetRemoteCertificate(remote_cert_copy.get());
409
410 // Configure MockWebRtcSession
411 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
412 .WillOnce(Return(transport.get()));
413 EXPECT_CALL(session_, GetStats(_))
414 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
415 Return(true)));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000416 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
417 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000418
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000419 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000420
421 stats.GetStats(NULL, &reports);
422
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000423 const StatsReport* channel_report = FindNthReportByType(
424 reports, StatsReport::kStatsReportTypeComponent, 1);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000425 EXPECT_TRUE(channel_report != NULL);
426
427 // Check local certificate chain.
428 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000429 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000430 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000431 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000432 if (local_ders.size() > 0) {
433 EXPECT_NE(kNotFound, local_certificate_id);
434 CheckCertChainReports(reports, local_ders, local_certificate_id);
435 } else {
436 EXPECT_EQ(kNotFound, local_certificate_id);
437 }
wu@webrtc.org4551b792013-10-09 15:37:36 +0000438
439 // Check remote certificate chain.
440 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000441 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000442 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000443 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000444 if (remote_ders.size() > 0) {
445 EXPECT_NE(kNotFound, remote_certificate_id);
446 CheckCertChainReports(reports, remote_ders, remote_certificate_id);
447 } else {
448 EXPECT_EQ(kNotFound, remote_certificate_id);
449 }
wu@webrtc.org4551b792013-10-09 15:37:36 +0000450 }
wu@webrtc.org97077a32013-10-25 21:18:33 +0000451
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452 cricket::FakeMediaEngine* media_engine_;
453 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
454 MockWebRtcSession session_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000455 cricket::SessionStats session_stats_;
456 talk_base::scoped_refptr<webrtc::MediaStream> stream_;
457 talk_base::scoped_refptr<webrtc::VideoTrack> track_;
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000458 talk_base::scoped_refptr<FakeLocalAudioTrack> audio_track_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000459 std::string track_id_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460};
461
462// This test verifies that 64-bit counters are passed successfully.
463TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
464 webrtc::StatsCollector stats; // Implementation under test.
465 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
466 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
467 media_engine_, media_channel, &session_, "", false, NULL);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000468 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000469 cricket::VideoSenderInfo video_sender_info;
470 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 // The number of bytes must be larger than 0xFFFFFFFF for this test.
472 const int64 kBytesSent = 12345678901234LL;
473 const std::string kBytesSentString("12345678901234");
474
475 stats.set_session(&session_);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000476 AddVideoTrackStats();
477 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478
479 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000480 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481 video_sender_info.bytes_sent = kBytesSent;
482 stats_read.senders.push_back(video_sender_info);
483
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000484 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
485 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000486 EXPECT_CALL(*media_channel, GetStats(_, _))
487 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 Return(true)));
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000489 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490 stats.GetStats(NULL, &reports);
491 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
492 EXPECT_EQ(kBytesSentString, result);
493}
494
495// Test that BWE information is reported via stats.
496TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
497 webrtc::StatsCollector stats; // Implementation under test.
498 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
499 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
500 media_engine_, media_channel, &session_, "", false, NULL);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000501 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 cricket::VideoSenderInfo video_sender_info;
503 cricket::VideoMediaInfo stats_read;
504 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
505 // BWE.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 const int64 kBytesSent = 12345678901234LL;
507 const std::string kBytesSentString("12345678901234");
508
509 stats.set_session(&session_);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000510 AddVideoTrackStats();
511 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512
513 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000514 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000515 video_sender_info.bytes_sent = kBytesSent;
516 stats_read.senders.push_back(video_sender_info);
517 cricket::BandwidthEstimationInfo bwe;
518 const int kTargetEncBitrate = 123456;
519 const std::string kTargetEncBitrateString("123456");
520 bwe.target_enc_bitrate = kTargetEncBitrate;
521 stats_read.bw_estimations.push_back(bwe);
522
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000523 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
524 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000525 EXPECT_CALL(*media_channel, GetStats(_, _))
526 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000528
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000529 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000530 stats.GetStats(NULL, &reports);
531 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
532 EXPECT_EQ(kBytesSentString, result);
533 result = ExtractBweStatsValue(reports, "googTargetEncBitrate");
534 EXPECT_EQ(kTargetEncBitrateString, result);
535}
536
537// This test verifies that an object of type "googSession" always
538// exists in the returned stats.
539TEST_F(StatsCollectorTest, SessionObjectExists) {
540 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000541 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 stats.set_session(&session_);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000543 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
544 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000545 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000547 const StatsReport* session_report = FindNthReportByType(
548 reports, StatsReport::kStatsReportTypeSession, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 EXPECT_FALSE(session_report == NULL);
550}
551
552// This test verifies that only one object of type "googSession" exists
553// in the returned stats.
554TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
555 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000556 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 stats.set_session(&session_);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000558 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
559 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000560 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
561 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000563 const StatsReport* session_report = FindNthReportByType(
564 reports, StatsReport::kStatsReportTypeSession, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 EXPECT_FALSE(session_report == NULL);
566 session_report = FindNthReportByType(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000567 reports, StatsReport::kStatsReportTypeSession, 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 EXPECT_EQ(NULL, session_report);
569}
570
571// This test verifies that the empty track report exists in the returned stats
572// without calling StatsCollector::UpdateStats.
573TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
574 webrtc::StatsCollector stats; // Implementation under test.
575 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
576 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
577 media_engine_, media_channel, &session_, "", false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000578 AddVideoTrackStats();
579 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580
581 stats.set_session(&session_);
582
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000583 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000584
585 // Verfies the existence of the track report.
586 stats.GetStats(NULL, &reports);
587 EXPECT_EQ((size_t)1, reports.size());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000588 EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 reports[0].type);
590
591 std::string trackValue =
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000592 ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000593 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000594 StatsReport::kStatsValueNameTrackId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 EXPECT_EQ(kTrackId, trackValue);
596}
597
598// This test verifies that the empty track report exists in the returned stats
599// when StatsCollector::UpdateStats is called with ssrc stats.
600TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
601 webrtc::StatsCollector stats; // Implementation under test.
602 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
603 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
604 media_engine_, media_channel, &session_, "", false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000605 AddVideoTrackStats();
606 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607
608 stats.set_session(&session_);
609
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000610 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611
612 // Constructs an ssrc stats update.
613 cricket::VideoSenderInfo video_sender_info;
614 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 const int64 kBytesSent = 12345678901234LL;
616
617 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000618 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000619 video_sender_info.bytes_sent = kBytesSent;
620 stats_read.senders.push_back(video_sender_info);
621
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000622 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
623 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000624 EXPECT_CALL(*media_channel, GetStats(_, _))
625 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000626 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000628 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629 stats.GetStats(NULL, &reports);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000630 // |reports| should contain at least one session report, one track report,
631 // and one ssrc report.
632 EXPECT_LE((size_t)3, reports.size());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000633 const StatsReport* track_report = FindNthReportByType(
634 reports, StatsReport::kStatsReportTypeTrack, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000635 EXPECT_FALSE(track_report == NULL);
636
wu@webrtc.org97077a32013-10-25 21:18:33 +0000637 stats.GetStats(track_, &reports);
638 // |reports| should contain at least one session report, one track report,
639 // and one ssrc report.
640 EXPECT_LE((size_t)3, reports.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000641 track_report = FindNthReportByType(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000642 reports, StatsReport::kStatsReportTypeTrack, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643 EXPECT_FALSE(track_report == NULL);
644
645 std::string ssrc_id = ExtractSsrcStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000646 reports, StatsReport::kStatsValueNameSsrc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
648
649 std::string track_id = ExtractSsrcStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000650 reports, StatsReport::kStatsValueNameTrackId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000651 EXPECT_EQ(kTrackId, track_id);
652}
653
654// This test verifies that an SSRC object has the identifier of a Transport
655// stats object, and that this transport stats object exists in stats.
656TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
657 webrtc::StatsCollector stats; // Implementation under test.
658 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
659 // The content_name known by the video channel.
660 const std::string kVcName("vcname");
661 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
662 media_engine_, media_channel, &session_, kVcName, false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000663 AddVideoTrackStats();
664 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665
666 stats.set_session(&session_);
667
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000668 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669
670 // Constructs an ssrc stats update.
671 cricket::VideoSenderInfo video_sender_info;
672 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 const int64 kBytesSent = 12345678901234LL;
674
675 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000676 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 video_sender_info.bytes_sent = kBytesSent;
678 stats_read.senders.push_back(video_sender_info);
679
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000680 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
681 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000682 EXPECT_CALL(*media_channel, GetStats(_, _))
683 .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000685
wu@webrtc.org97077a32013-10-25 21:18:33 +0000686 InitSessionStats(kVcName);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000687 EXPECT_CALL(session_, GetStats(_))
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000688 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
689 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000690
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000691 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000692 stats.GetStats(NULL, &reports);
693 std::string transport_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000694 StatsReport::kStatsReportTypeSsrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000695 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000696 StatsReport::kStatsValueNameTransportId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000697 ASSERT_NE(kNotFound, transport_id);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000698 const StatsReport* transport_report = FindReportById(reports,
699 transport_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000700 ASSERT_FALSE(transport_report == NULL);
701}
702
wu@webrtc.org97077a32013-10-25 21:18:33 +0000703// This test verifies that a remote stats object will not be created for
704// an outgoing SSRC where remote stats are not returned.
705TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
706 webrtc::StatsCollector stats; // Implementation under test.
707 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
708 // The content_name known by the video channel.
709 const std::string kVcName("vcname");
710 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
711 media_engine_, media_channel, &session_, kVcName, false, NULL);
712 AddVideoTrackStats();
713 stats.AddStream(stream_);
714
715 stats.set_session(&session_);
716
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000717 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
718 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org97077a32013-10-25 21:18:33 +0000719
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000720 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000721 StatsReports reports;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000722 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000723 const StatsReport* remote_report = FindNthReportByType(reports,
724 StatsReport::kStatsReportTypeRemoteSsrc, 1);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000725 EXPECT_TRUE(remote_report == NULL);
726}
727
728// This test verifies that a remote stats object will be created for
729// an outgoing SSRC where stats are returned.
730TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
731 webrtc::StatsCollector stats; // Implementation under test.
732 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
733 // The content_name known by the video channel.
734 const std::string kVcName("vcname");
735 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
736 media_engine_, media_channel, &session_, kVcName, false, NULL);
737 AddVideoTrackStats();
738 stats.AddStream(stream_);
739
740 stats.set_session(&session_);
741
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000742 StatsReports reports;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000743
744 // Instruct the session to return stats containing the transport channel.
745 InitSessionStats(kVcName);
746 EXPECT_CALL(session_, GetStats(_))
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000747 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
748 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000749
750 // Constructs an ssrc stats update.
751 cricket::VideoMediaInfo stats_read;
752
753 cricket::SsrcReceiverInfo remote_ssrc_stats;
754 remote_ssrc_stats.timestamp = 12345.678;
755 remote_ssrc_stats.ssrc = kSsrcOfTrack;
756 cricket::VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000757 video_sender_info.add_ssrc(kSsrcOfTrack);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000758 video_sender_info.remote_stats.push_back(remote_ssrc_stats);
759 stats_read.senders.push_back(video_sender_info);
760
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000761 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
762 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000763 EXPECT_CALL(*media_channel, GetStats(_, _))
764 .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
wu@webrtc.org97077a32013-10-25 21:18:33 +0000765 Return(true)));
766
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000767 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000768 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000769 const StatsReport* remote_report = FindNthReportByType(reports,
770 StatsReport::kStatsReportTypeRemoteSsrc, 1);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000771 EXPECT_FALSE(remote_report == NULL);
772 EXPECT_NE(0, remote_report->timestamp);
773}
774
wu@webrtc.org4551b792013-10-09 15:37:36 +0000775// This test verifies that all chained certificates are correctly
776// reported
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000777TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000778 // Build local certificate chain.
779 std::vector<std::string> local_ders(5);
780 local_ders[0] = "These";
781 local_ders[1] = "are";
782 local_ders[2] = "some";
783 local_ders[3] = "der";
784 local_ders[4] = "values";
785 talk_base::FakeSSLCertificate local_cert(DersToPems(local_ders));
786
787 // Build remote certificate chain
788 std::vector<std::string> remote_ders(4);
789 remote_ders[0] = "A";
790 remote_ders[1] = "non-";
791 remote_ders[2] = "intersecting";
792 remote_ders[3] = "set";
793 talk_base::FakeSSLCertificate remote_cert(DersToPems(remote_ders));
794
795 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders);
796}
797
798// This test verifies that all certificates without chains are correctly
799// reported.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000800TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000801 // Build local certificate.
802 std::string local_der = "This is the local der.";
803 talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
804
805 // Build remote certificate.
806 std::string remote_der = "This is somebody else's der.";
807 talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
808
809 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
810 remote_cert, std::vector<std::string>(1, remote_der));
811}
812
813// This test verifies that the stats are generated correctly when no
814// transport is present.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000815TEST_F(StatsCollectorTest, NoTransport) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000816 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000817 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000818 stats.set_session(&session_);
819
820 // Fake stats to process.
821 cricket::TransportChannelStats channel_stats;
822 channel_stats.component = 1;
823
824 cricket::TransportStats transport_stats;
825 transport_stats.content_name = "audio";
826 transport_stats.channel_stats.push_back(channel_stats);
827
828 cricket::SessionStats session_stats;
829 session_stats.transport_stats[transport_stats.content_name] =
830 transport_stats;
831
832 // Configure MockWebRtcSession
833 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
834 .WillOnce(ReturnNull());
835 EXPECT_CALL(session_, GetStats(_))
836 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
837 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000838
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000839 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
840 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000841
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000842 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000843 stats.GetStats(NULL, &reports);
844
845 // Check that the local certificate is absent.
846 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000847 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000848 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000849 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000850 ASSERT_EQ(kNotFound, local_certificate_id);
851
852 // Check that the remote certificate is absent.
853 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000854 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000855 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000856 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000857 ASSERT_EQ(kNotFound, remote_certificate_id);
858}
859
860// This test verifies that the stats are generated correctly when the transport
861// does not have any certificates.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000862TEST_F(StatsCollectorTest, NoCertificates) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000863 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000864 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000865 stats.set_session(&session_);
866
867 // Fake stats to process.
868 cricket::TransportChannelStats channel_stats;
869 channel_stats.component = 1;
870
871 cricket::TransportStats transport_stats;
872 transport_stats.content_name = "audio";
873 transport_stats.channel_stats.push_back(channel_stats);
874
875 cricket::SessionStats session_stats;
876 session_stats.transport_stats[transport_stats.content_name] =
877 transport_stats;
878
879 // Fake transport object.
880 talk_base::scoped_ptr<cricket::FakeTransport> transport(
881 new cricket::FakeTransport(
882 session_.signaling_thread(),
883 session_.worker_thread(),
884 transport_stats.content_name));
885
886 // Configure MockWebRtcSession
887 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
888 .WillOnce(Return(transport.get()));
889 EXPECT_CALL(session_, GetStats(_))
890 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
891 Return(true)));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000892 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
893 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000894
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000895 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000896 stats.GetStats(NULL, &reports);
897
898 // Check that the local certificate is absent.
899 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000900 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000901 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000902 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000903 ASSERT_EQ(kNotFound, local_certificate_id);
904
905 // Check that the remote certificate is absent.
906 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000907 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000908 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000909 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000910 ASSERT_EQ(kNotFound, remote_certificate_id);
911}
912
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000913// This test verifies that a remote certificate with an unsupported digest
914// algorithm is correctly ignored.
915TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
916 // Build a local certificate.
917 std::string local_der = "This is the local der.";
918 talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
919
920 // Build a remote certificate with an unsupported digest algorithm.
921 std::string remote_der = "This is somebody else's der.";
922 talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
923 remote_cert.set_digest_algorithm("foobar");
924
925 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
926 remote_cert, std::vector<std::string>());
927}
928
929// Verifies the correct optons are passed to the VideoMediaChannel when using
930// verbose output level.
931TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
932 webrtc::StatsCollector stats; // Implementation under test.
933 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
934 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
935 media_engine_, media_channel, &session_, "", false, NULL);
936 stats.set_session(&session_);
937
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000938 StatsReports reports; // returned values.
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000939 cricket::VideoMediaInfo stats_read;
940 cricket::BandwidthEstimationInfo bwe;
941 bwe.total_received_propagation_delta_ms = 10;
942 bwe.recent_received_propagation_delta_ms.push_back(100);
943 bwe.recent_received_propagation_delta_ms.push_back(200);
944 bwe.recent_received_packet_group_arrival_time_ms.push_back(1000);
945 bwe.recent_received_packet_group_arrival_time_ms.push_back(2000);
946 stats_read.bw_estimations.push_back(bwe);
947
948 EXPECT_CALL(session_, video_channel())
949 .WillRepeatedly(Return(&video_channel));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000950 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000951
952 StatsOptions options;
953 options.include_received_propagation_stats = true;
954 EXPECT_CALL(*media_channel, GetStats(
955 Field(&StatsOptions::include_received_propagation_stats, true),
956 _))
957 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
958 Return(true)));
959
960 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelDebug);
961 stats.GetStats(NULL, &reports);
962 std::string result = ExtractBweStatsValue(
963 reports, "googReceivedPacketGroupPropagationDeltaSumDebug");
964 EXPECT_EQ("10", result);
965 result = ExtractBweStatsValue(
966 reports, "googReceivedPacketGroupPropagationDeltaDebug");
967 EXPECT_EQ("[100, 200]", result);
968 result = ExtractBweStatsValue(
969 reports, "googReceivedPacketGroupArrivalTimeDebug");
970 EXPECT_EQ("[1000, 2000]", result);
971}
972
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000973// This test verifies that a local stats object can get statistics via
974// AudioTrackInterface::GetStats() method.
975TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
976 webrtc::StatsCollector stats; // Implementation under test.
977 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
978 // The content_name known by the voice channel.
979 const std::string kVcName("vcname");
980 cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
981 media_engine_, media_channel, &session_, kVcName, false);
982 AddLocalAudioTrackStats();
983 stats.AddStream(stream_);
984 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
985
986 stats.set_session(&session_);
987
988 // Instruct the session to return stats containing the transport channel.
989 InitSessionStats(kVcName);
990 EXPECT_CALL(session_, GetStats(_))
991 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
992 Return(true)));
993
994 cricket::VoiceSenderInfo voice_sender_info;
995 // Contents won't be modified by the AudioTrackInterface::GetStats().
996 voice_sender_info.add_ssrc(kSsrcOfTrack);
997 voice_sender_info.codec_name = "fake_codec";
998 voice_sender_info.bytes_sent = 100;
999 voice_sender_info.packets_sent = 101;
1000 voice_sender_info.rtt_ms = 102;
1001 voice_sender_info.fraction_lost = 103;
1002 voice_sender_info.jitter_ms = 104;
1003 voice_sender_info.packets_lost = 105;
1004 voice_sender_info.ext_seqnum = 106;
1005
1006 // Contents will be modified by the AudioTrackInterface::GetStats().
1007 voice_sender_info.audio_level = 107;
1008 voice_sender_info.echo_return_loss = 108;;
1009 voice_sender_info.echo_return_loss_enhancement = 109;
1010 voice_sender_info.echo_delay_median_ms = 110;
1011 voice_sender_info.echo_delay_std_ms = 111;
1012 voice_sender_info.aec_quality_min = 112.0f;
1013 voice_sender_info.typing_noise_detected = false;
1014
1015 // Constructs an ssrc stats update.
1016 cricket::VoiceMediaInfo stats_read;
1017 stats_read.senders.push_back(voice_sender_info);
1018
1019 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
1020 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
1021 EXPECT_CALL(*media_channel, GetStats(_))
1022 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
1023 Return(true)));
1024
1025 StatsReports reports; // returned values.
1026 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1027 stats.GetStats(NULL, &reports);
1028
1029 // Verfy the existence of the track report.
1030 const StatsReport* report = FindNthReportByType(
1031 reports, StatsReport::kStatsReportTypeSsrc, 1);
1032 EXPECT_FALSE(report == NULL);
1033 std::string track_id = ExtractSsrcStatsValue(
1034 reports, StatsReport::kStatsValueNameTrackId);
1035 EXPECT_EQ(kAudioTrackId, track_id);
1036 std::string ssrc_id = ExtractSsrcStatsValue(
1037 reports, StatsReport::kStatsValueNameSsrc);
1038 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1039
1040 // Verifies the values in the track report.
1041 audio_track_->GetSignalLevel(&voice_sender_info.audio_level);
1042 webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats;
1043 audio_track_->GetAudioProcessor()->GetStats(&audio_processor_stats);
1044 voice_sender_info.typing_noise_detected =
1045 audio_processor_stats.typing_noise_detected;
1046 voice_sender_info.echo_return_loss = audio_processor_stats.echo_return_loss;
1047 voice_sender_info.echo_return_loss_enhancement =
1048 audio_processor_stats.echo_return_loss_enhancement;
1049 voice_sender_info.echo_delay_median_ms =
1050 audio_processor_stats.echo_delay_median_ms;
1051 voice_sender_info.aec_quality_min = audio_processor_stats.aec_quality_min;
1052 voice_sender_info.echo_delay_std_ms = audio_processor_stats.echo_delay_std_ms;
1053 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1054
1055 // Verify we get the same result by passing a track to GetStats().
1056 StatsReports track_reports; // returned values.
1057 stats.GetStats(audio_track_.get(), &track_reports);
1058 const StatsReport* track_report = FindNthReportByType(
1059 track_reports, StatsReport::kStatsReportTypeSsrc, 1);
1060 EXPECT_FALSE(track_report == NULL);
1061 track_id = ExtractSsrcStatsValue(track_reports,
1062 StatsReport::kStatsValueNameTrackId);
1063 EXPECT_EQ(kAudioTrackId, track_id);
1064 ssrc_id = ExtractSsrcStatsValue(track_reports,
1065 StatsReport::kStatsValueNameSsrc);
1066 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1067 VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
1068}
1069
1070// This test verifies that a local stats object won't update its statistics
1071// after a RemoveLocalAudioTrack() call.
1072TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
1073 webrtc::StatsCollector stats; // Implementation under test.
1074 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
1075 // The content_name known by the voice channel.
1076 const std::string kVcName("vcname");
1077 cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
1078 media_engine_, media_channel, &session_, kVcName, false);
1079 AddLocalAudioTrackStats();
1080 stats.AddStream(stream_);
1081 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1082
1083 stats.set_session(&session_);
1084
1085 // Instruct the session to return stats containing the transport channel.
1086 InitSessionStats(kVcName);
1087 EXPECT_CALL(session_, GetStats(_))
1088 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
1089 Return(true)));
1090
1091 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1092 cricket::VoiceSenderInfo voice_sender_info;
1093 // Contents won't be modified by the AudioTrackInterface::GetStats().
1094 voice_sender_info.add_ssrc(kSsrcOfTrack);
1095 voice_sender_info.codec_name = "fake_codec";
1096 voice_sender_info.bytes_sent = 100;
1097 voice_sender_info.packets_sent = 101;
1098 voice_sender_info.rtt_ms = 102;
1099 voice_sender_info.fraction_lost = 103;
1100 voice_sender_info.jitter_ms = 104;
1101 voice_sender_info.packets_lost = 105;
1102 voice_sender_info.ext_seqnum = 106;
1103
1104 // Contents will be modified by the AudioTrackInterface::GetStats().
1105 voice_sender_info.audio_level = 107;
1106 voice_sender_info.echo_return_loss = 108;;
1107 voice_sender_info.echo_return_loss_enhancement = 109;
1108 voice_sender_info.echo_delay_median_ms = 110;
1109 voice_sender_info.echo_delay_std_ms = 111;
1110 voice_sender_info.aec_quality_min = 112;
1111 voice_sender_info.typing_noise_detected = false;
1112
1113 // Constructs an ssrc stats update.
1114 cricket::VoiceMediaInfo stats_read;
1115 stats_read.senders.push_back(voice_sender_info);
1116
1117 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
1118 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
1119 EXPECT_CALL(*media_channel, GetStats(_))
1120 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
1121 Return(true)));
1122
1123 StatsReports reports; // returned values.
1124 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1125 stats.GetStats(NULL, &reports);
1126
1127 // The report will exist since we don't remove them in RemoveStream().
1128 const StatsReport* report = FindNthReportByType(
1129 reports, StatsReport::kStatsReportTypeSsrc, 1);
1130 EXPECT_FALSE(report == NULL);
1131 std::string track_id = ExtractSsrcStatsValue(
1132 reports, StatsReport::kStatsValueNameTrackId);
1133 EXPECT_EQ(kAudioTrackId, track_id);
1134 std::string ssrc_id = ExtractSsrcStatsValue(
1135 reports, StatsReport::kStatsValueNameSsrc);
1136 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1137
1138 // Verifies the values in the track report, no value will be changed by the
1139 // AudioTrackInterface::GetSignalValue() and
1140 // AudioProcessorInterface::AudioProcessorStats::GetStats();
1141 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1142}
1143
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001144} // namespace