blob: 83d214c463da4d27dac5ca670ab0340ebbe0472e [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 }
137 virtual webrtc::AudioProcessorInterface* GetAudioProcessor() OVERRIDE {
138 return processor_.get();
139 }
140
141 private:
142 talk_base::scoped_refptr<FakeAudioProcessor> processor_;
143};
144
145bool GetValue(const StatsReport* report,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000146 const std::string& name,
147 std::string* value) {
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000148 StatsReport::Values::const_iterator it = report->values.begin();
wu@webrtc.org4551b792013-10-09 15:37:36 +0000149 for (; it != report->values.end(); ++it) {
150 if (it->name == name) {
151 *value = it->value;
152 return true;
153 }
154 }
155 return false;
156}
157
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000158std::string ExtractStatsValue(const std::string& type,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000159 const StatsReports& reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160 const std::string name) {
161 if (reports.empty()) {
162 return kNoReports;
163 }
164 for (size_t i = 0; i < reports.size(); ++i) {
165 if (reports[i].type != type)
166 continue;
wu@webrtc.org4551b792013-10-09 15:37:36 +0000167 std::string ret;
168 if (GetValue(&reports[i], name, &ret)) {
169 return ret;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170 }
171 }
172
173 return kNotFound;
174}
175
176// Finds the |n|-th report of type |type| in |reports|.
177// |n| starts from 1 for finding the first report.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000178const StatsReport* FindNthReportByType(
179 const StatsReports& reports, const std::string& type, int n) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000180 for (size_t i = 0; i < reports.size(); ++i) {
181 if (reports[i].type == type) {
182 n--;
183 if (n == 0)
184 return &reports[i];
185 }
186 }
187 return NULL;
188}
189
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000190const StatsReport* FindReportById(const StatsReports& reports,
191 const std::string& id) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192 for (size_t i = 0; i < reports.size(); ++i) {
193 if (reports[i].id == id) {
194 return &reports[i];
195 }
196 }
197 return NULL;
198}
199
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000200std::string ExtractSsrcStatsValue(StatsReports reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201 const std::string& name) {
202 return ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000203 StatsReport::kStatsReportTypeSsrc, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000204}
205
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000206std::string ExtractBweStatsValue(StatsReports reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 const std::string& name) {
208 return ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000209 StatsReport::kStatsReportTypeBwe, reports, name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000210}
211
wu@webrtc.org4551b792013-10-09 15:37:36 +0000212std::string DerToPem(const std::string& der) {
213 return talk_base::SSLIdentity::DerToPem(
214 talk_base::kPemTypeCertificate,
215 reinterpret_cast<const unsigned char*>(der.c_str()),
216 der.length());
217}
218
219std::vector<std::string> DersToPems(
220 const std::vector<std::string>& ders) {
221 std::vector<std::string> pems(ders.size());
222 std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem);
223 return pems;
224}
225
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000226void CheckCertChainReports(const StatsReports& reports,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000227 const std::vector<std::string>& ders,
228 const std::string& start_id) {
229 std::string certificate_id = start_id;
230 size_t i = 0;
231 while (true) {
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000232 const StatsReport* report = FindReportById(reports, certificate_id);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000233 ASSERT_TRUE(report != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000234
wu@webrtc.org4551b792013-10-09 15:37:36 +0000235 std::string der_base64;
236 EXPECT_TRUE(GetValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000237 report, StatsReport::kStatsValueNameDer, &der_base64));
wu@webrtc.org4551b792013-10-09 15:37:36 +0000238 std::string der = talk_base::Base64::Decode(der_base64,
239 talk_base::Base64::DO_STRICT);
240 EXPECT_EQ(ders[i], der);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000241
242 std::string fingerprint_algorithm;
243 EXPECT_TRUE(GetValue(
244 report,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000245 StatsReport::kStatsValueNameFingerprintAlgorithm,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000246 &fingerprint_algorithm));
247 // The digest algorithm for a FakeSSLCertificate is always SHA-1.
248 std::string sha_1_str = talk_base::DIGEST_SHA_1;
249 EXPECT_EQ(sha_1_str, fingerprint_algorithm);
250
251 std::string dummy_fingerprint; // Value is not checked.
252 EXPECT_TRUE(GetValue(
253 report,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000254 StatsReport::kStatsValueNameFingerprint,
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000255 &dummy_fingerprint));
256
wu@webrtc.org4551b792013-10-09 15:37:36 +0000257 ++i;
258 if (!GetValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000259 report, StatsReport::kStatsValueNameIssuerId, &certificate_id))
wu@webrtc.org4551b792013-10-09 15:37:36 +0000260 break;
261 }
262 EXPECT_EQ(ders.size(), i);
263}
264
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000265void VerifyVoiceSenderInfoReport(const StatsReport* report,
266 const cricket::VoiceSenderInfo& sinfo) {
267 std::string value_in_report;
268 EXPECT_TRUE(GetValue(
269 report, StatsReport::kStatsValueNameCodecName, &value_in_report));
270 EXPECT_EQ(sinfo.codec_name, value_in_report);
271 EXPECT_TRUE(GetValue(
272 report, StatsReport::kStatsValueNameBytesSent, &value_in_report));
273 EXPECT_EQ(talk_base::ToString<int64>(sinfo.bytes_sent), value_in_report);
274 EXPECT_TRUE(GetValue(
275 report, StatsReport::kStatsValueNamePacketsSent, &value_in_report));
276 EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_sent), value_in_report);
277 EXPECT_TRUE(GetValue(
278 report, StatsReport::kStatsValueNameRtt, &value_in_report));
279 EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
280 EXPECT_TRUE(GetValue(
281 report, StatsReport::kStatsValueNameRtt, &value_in_report));
282 EXPECT_EQ(talk_base::ToString<int>(sinfo.rtt_ms), value_in_report);
283 EXPECT_TRUE(GetValue(
284 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report));
285 EXPECT_EQ(talk_base::ToString<int>(sinfo.jitter_ms), value_in_report);
286 EXPECT_TRUE(GetValue(
287 report, StatsReport::kStatsValueNameEchoCancellationQualityMin,
288 &value_in_report));
289 EXPECT_EQ(talk_base::ToString<float>(sinfo.aec_quality_min), value_in_report);
290 EXPECT_TRUE(GetValue(
291 report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report));
292 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_median_ms),
293 value_in_report);
294 EXPECT_TRUE(GetValue(
295 report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report));
296 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_delay_std_ms),
297 value_in_report);
298 EXPECT_TRUE(GetValue(
299 report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report));
300 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss),
301 value_in_report);
302 EXPECT_TRUE(GetValue(
303 report, StatsReport::kStatsValueNameEchoReturnLossEnhancement,
304 &value_in_report));
305 EXPECT_EQ(talk_base::ToString<int>(sinfo.echo_return_loss_enhancement),
306 value_in_report);
307 EXPECT_TRUE(GetValue(
308 report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report));
309 EXPECT_EQ(talk_base::ToString<int>(sinfo.audio_level), value_in_report);
310 EXPECT_TRUE(GetValue(
311 report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report));
312 std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false";
313 EXPECT_EQ(typing_detected, value_in_report);
314}
315
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316class StatsCollectorTest : public testing::Test {
317 protected:
318 StatsCollectorTest()
319 : media_engine_(new cricket::FakeMediaEngine),
320 channel_manager_(
321 new cricket::ChannelManager(media_engine_,
322 new cricket::FakeDeviceManager(),
323 talk_base::Thread::Current())),
wu@webrtc.org97077a32013-10-25 21:18:33 +0000324 session_(channel_manager_.get()),
325 track_id_(kTrackId) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 // By default, we ignore session GetStats calls.
327 EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
328 }
329
wu@webrtc.org97077a32013-10-25 21:18:33 +0000330 // This creates a standard setup with a transport called "trspname"
331 // having one transport channel
332 // and the specified virtual connection name.
333 void InitSessionStats(const std::string vc_name) {
334 const std::string kTransportName("trspname");
335 cricket::TransportStats transport_stats;
336 cricket::TransportChannelStats channel_stats;
337 channel_stats.component = 1;
338 transport_stats.content_name = kTransportName;
339 transport_stats.channel_stats.push_back(channel_stats);
340
341 session_stats_.transport_stats[kTransportName] = transport_stats;
342 session_stats_.proxy_to_transport[vc_name] = kTransportName;
343 }
344
345 // Adds a track with a given SSRC into the stats.
346 void AddVideoTrackStats() {
347 stream_ = webrtc::MediaStream::Create("streamlabel");
348 track_= webrtc::VideoTrack::Create(kTrackId, NULL);
349 stream_->AddTrack(track_);
350 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
351 .WillRepeatedly(DoAll(SetArgPointee<1>(track_id_),
352 Return(true)));
353 }
354
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000355 // Adds a local audio track with a given SSRC into the stats.
356 void AddLocalAudioTrackStats() {
357 if (stream_ == NULL)
358 stream_ = webrtc::MediaStream::Create("streamlabel");
359
360 audio_track_ =
361 new talk_base::RefCountedObject<FakeLocalAudioTrack>(kAudioTrackId);
362 stream_->AddTrack(audio_track_);
363 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
364 .WillRepeatedly(DoAll(SetArgPointee<1>(kAudioTrackId),
365 Return(true)));
366 }
367
wu@webrtc.org4551b792013-10-09 15:37:36 +0000368 void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
369 const std::vector<std::string>& local_ders,
370 const talk_base::FakeSSLCertificate& remote_cert,
371 const std::vector<std::string>& remote_ders) {
372 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000373 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000374 stats.set_session(&session_);
375
376 // Fake stats to process.
377 cricket::TransportChannelStats channel_stats;
378 channel_stats.component = 1;
379
380 cricket::TransportStats transport_stats;
381 transport_stats.content_name = "audio";
382 transport_stats.channel_stats.push_back(channel_stats);
383
384 cricket::SessionStats session_stats;
385 session_stats.transport_stats[transport_stats.content_name] =
386 transport_stats;
387
388 // Fake certificates to report.
389 talk_base::FakeSSLIdentity local_identity(local_cert);
390 talk_base::scoped_ptr<talk_base::FakeSSLCertificate> remote_cert_copy(
391 remote_cert.GetReference());
392
393 // Fake transport object.
394 talk_base::scoped_ptr<cricket::FakeTransport> transport(
395 new cricket::FakeTransport(
396 session_.signaling_thread(),
397 session_.worker_thread(),
398 transport_stats.content_name));
399 transport->SetIdentity(&local_identity);
400 cricket::FakeTransportChannel* channel =
401 static_cast<cricket::FakeTransportChannel*>(
402 transport->CreateChannel(channel_stats.component));
403 EXPECT_FALSE(channel == NULL);
404 channel->SetRemoteCertificate(remote_cert_copy.get());
405
406 // Configure MockWebRtcSession
407 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
408 .WillOnce(Return(transport.get()));
409 EXPECT_CALL(session_, GetStats(_))
410 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
411 Return(true)));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000412 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
413 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000414
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000415 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000416
417 stats.GetStats(NULL, &reports);
418
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000419 const StatsReport* channel_report = FindNthReportByType(
420 reports, StatsReport::kStatsReportTypeComponent, 1);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000421 EXPECT_TRUE(channel_report != NULL);
422
423 // Check local certificate chain.
424 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000425 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000426 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000427 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000428 if (local_ders.size() > 0) {
429 EXPECT_NE(kNotFound, local_certificate_id);
430 CheckCertChainReports(reports, local_ders, local_certificate_id);
431 } else {
432 EXPECT_EQ(kNotFound, local_certificate_id);
433 }
wu@webrtc.org4551b792013-10-09 15:37:36 +0000434
435 // Check remote certificate chain.
436 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000437 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000438 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000439 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000440 if (remote_ders.size() > 0) {
441 EXPECT_NE(kNotFound, remote_certificate_id);
442 CheckCertChainReports(reports, remote_ders, remote_certificate_id);
443 } else {
444 EXPECT_EQ(kNotFound, remote_certificate_id);
445 }
wu@webrtc.org4551b792013-10-09 15:37:36 +0000446 }
wu@webrtc.org97077a32013-10-25 21:18:33 +0000447
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 cricket::FakeMediaEngine* media_engine_;
449 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
450 MockWebRtcSession session_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000451 cricket::SessionStats session_stats_;
452 talk_base::scoped_refptr<webrtc::MediaStream> stream_;
453 talk_base::scoped_refptr<webrtc::VideoTrack> track_;
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000454 talk_base::scoped_refptr<FakeLocalAudioTrack> audio_track_;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000455 std::string track_id_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456};
457
458// This test verifies that 64-bit counters are passed successfully.
459TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
460 webrtc::StatsCollector stats; // Implementation under test.
461 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
462 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
463 media_engine_, media_channel, &session_, "", false, NULL);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000464 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465 cricket::VideoSenderInfo video_sender_info;
466 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 // The number of bytes must be larger than 0xFFFFFFFF for this test.
468 const int64 kBytesSent = 12345678901234LL;
469 const std::string kBytesSentString("12345678901234");
470
471 stats.set_session(&session_);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000472 AddVideoTrackStats();
473 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474
475 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000476 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477 video_sender_info.bytes_sent = kBytesSent;
478 stats_read.senders.push_back(video_sender_info);
479
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000480 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
481 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000482 EXPECT_CALL(*media_channel, GetStats(_, _))
483 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 Return(true)));
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000485 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 stats.GetStats(NULL, &reports);
487 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
488 EXPECT_EQ(kBytesSentString, result);
489}
490
491// Test that BWE information is reported via stats.
492TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
493 webrtc::StatsCollector stats; // Implementation under test.
494 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
495 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
496 media_engine_, media_channel, &session_, "", false, NULL);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000497 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000498 cricket::VideoSenderInfo video_sender_info;
499 cricket::VideoMediaInfo stats_read;
500 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
501 // BWE.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000502 const int64 kBytesSent = 12345678901234LL;
503 const std::string kBytesSentString("12345678901234");
504
505 stats.set_session(&session_);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000506 AddVideoTrackStats();
507 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508
509 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000510 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000511 video_sender_info.bytes_sent = kBytesSent;
512 stats_read.senders.push_back(video_sender_info);
513 cricket::BandwidthEstimationInfo bwe;
514 const int kTargetEncBitrate = 123456;
515 const std::string kTargetEncBitrateString("123456");
516 bwe.target_enc_bitrate = kTargetEncBitrate;
517 stats_read.bw_estimations.push_back(bwe);
518
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000519 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
520 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000521 EXPECT_CALL(*media_channel, GetStats(_, _))
522 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000524
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000525 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526 stats.GetStats(NULL, &reports);
527 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
528 EXPECT_EQ(kBytesSentString, result);
529 result = ExtractBweStatsValue(reports, "googTargetEncBitrate");
530 EXPECT_EQ(kTargetEncBitrateString, result);
531}
532
533// This test verifies that an object of type "googSession" always
534// exists in the returned stats.
535TEST_F(StatsCollectorTest, SessionObjectExists) {
536 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000537 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000538 stats.set_session(&session_);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000539 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
540 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000541 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000543 const StatsReport* session_report = FindNthReportByType(
544 reports, StatsReport::kStatsReportTypeSession, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 EXPECT_FALSE(session_report == NULL);
546}
547
548// This test verifies that only one object of type "googSession" exists
549// in the returned stats.
550TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
551 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000552 StatsReports reports; // returned values.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000553 stats.set_session(&session_);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000554 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
555 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000556 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
557 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000559 const StatsReport* session_report = FindNthReportByType(
560 reports, StatsReport::kStatsReportTypeSession, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000561 EXPECT_FALSE(session_report == NULL);
562 session_report = FindNthReportByType(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000563 reports, StatsReport::kStatsReportTypeSession, 2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564 EXPECT_EQ(NULL, session_report);
565}
566
567// This test verifies that the empty track report exists in the returned stats
568// without calling StatsCollector::UpdateStats.
569TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
570 webrtc::StatsCollector stats; // Implementation under test.
571 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
572 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
573 media_engine_, media_channel, &session_, "", false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000574 AddVideoTrackStats();
575 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576
577 stats.set_session(&session_);
578
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000579 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580
581 // Verfies the existence of the track report.
582 stats.GetStats(NULL, &reports);
583 EXPECT_EQ((size_t)1, reports.size());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000584 EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585 reports[0].type);
586
587 std::string trackValue =
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000588 ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000590 StatsReport::kStatsValueNameTrackId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 EXPECT_EQ(kTrackId, trackValue);
592}
593
594// This test verifies that the empty track report exists in the returned stats
595// when StatsCollector::UpdateStats is called with ssrc stats.
596TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
597 webrtc::StatsCollector stats; // Implementation under test.
598 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
599 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
600 media_engine_, media_channel, &session_, "", false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000601 AddVideoTrackStats();
602 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603
604 stats.set_session(&session_);
605
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000606 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000607
608 // Constructs an ssrc stats update.
609 cricket::VideoSenderInfo video_sender_info;
610 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000611 const int64 kBytesSent = 12345678901234LL;
612
613 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000614 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000615 video_sender_info.bytes_sent = kBytesSent;
616 stats_read.senders.push_back(video_sender_info);
617
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000618 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
619 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000620 EXPECT_CALL(*media_channel, GetStats(_, _))
621 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000622 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000623
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000624 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000625 stats.GetStats(NULL, &reports);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000626 // |reports| should contain at least one session report, one track report,
627 // and one ssrc report.
628 EXPECT_LE((size_t)3, reports.size());
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000629 const StatsReport* track_report = FindNthReportByType(
630 reports, StatsReport::kStatsReportTypeTrack, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631 EXPECT_FALSE(track_report == NULL);
632
wu@webrtc.org97077a32013-10-25 21:18:33 +0000633 stats.GetStats(track_, &reports);
634 // |reports| should contain at least one session report, one track report,
635 // and one ssrc report.
636 EXPECT_LE((size_t)3, reports.size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000637 track_report = FindNthReportByType(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000638 reports, StatsReport::kStatsReportTypeTrack, 1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639 EXPECT_FALSE(track_report == NULL);
640
641 std::string ssrc_id = ExtractSsrcStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000642 reports, StatsReport::kStatsValueNameSsrc);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000643 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
644
645 std::string track_id = ExtractSsrcStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000646 reports, StatsReport::kStatsValueNameTrackId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000647 EXPECT_EQ(kTrackId, track_id);
648}
649
650// This test verifies that an SSRC object has the identifier of a Transport
651// stats object, and that this transport stats object exists in stats.
652TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
653 webrtc::StatsCollector stats; // Implementation under test.
654 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
655 // The content_name known by the video channel.
656 const std::string kVcName("vcname");
657 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
658 media_engine_, media_channel, &session_, kVcName, false, NULL);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000659 AddVideoTrackStats();
660 stats.AddStream(stream_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661
662 stats.set_session(&session_);
663
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000664 StatsReports reports;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000665
666 // Constructs an ssrc stats update.
667 cricket::VideoSenderInfo video_sender_info;
668 cricket::VideoMediaInfo stats_read;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 const int64 kBytesSent = 12345678901234LL;
670
671 // Construct a stats value to read.
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000672 video_sender_info.add_ssrc(1234);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 video_sender_info.bytes_sent = kBytesSent;
674 stats_read.senders.push_back(video_sender_info);
675
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000676 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
677 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000678 EXPECT_CALL(*media_channel, GetStats(_, _))
679 .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681
wu@webrtc.org97077a32013-10-25 21:18:33 +0000682 InitSessionStats(kVcName);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000683 EXPECT_CALL(session_, GetStats(_))
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000684 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
685 Return(true)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000687 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 stats.GetStats(NULL, &reports);
689 std::string transport_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000690 StatsReport::kStatsReportTypeSsrc,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000692 StatsReport::kStatsValueNameTransportId);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 ASSERT_NE(kNotFound, transport_id);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000694 const StatsReport* transport_report = FindReportById(reports,
695 transport_id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000696 ASSERT_FALSE(transport_report == NULL);
697}
698
wu@webrtc.org97077a32013-10-25 21:18:33 +0000699// This test verifies that a remote stats object will not be created for
700// an outgoing SSRC where remote stats are not returned.
701TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) {
702 webrtc::StatsCollector stats; // Implementation under test.
703 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
704 // The content_name known by the video channel.
705 const std::string kVcName("vcname");
706 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
707 media_engine_, media_channel, &session_, kVcName, false, NULL);
708 AddVideoTrackStats();
709 stats.AddStream(stream_);
710
711 stats.set_session(&session_);
712
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000713 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
714 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org97077a32013-10-25 21:18:33 +0000715
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000716 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000717 StatsReports reports;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000718 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000719 const StatsReport* remote_report = FindNthReportByType(reports,
720 StatsReport::kStatsReportTypeRemoteSsrc, 1);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000721 EXPECT_TRUE(remote_report == NULL);
722}
723
724// This test verifies that a remote stats object will be created for
725// an outgoing SSRC where stats are returned.
726TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) {
727 webrtc::StatsCollector stats; // Implementation under test.
728 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
729 // The content_name known by the video channel.
730 const std::string kVcName("vcname");
731 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
732 media_engine_, media_channel, &session_, kVcName, false, NULL);
733 AddVideoTrackStats();
734 stats.AddStream(stream_);
735
736 stats.set_session(&session_);
737
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000738 StatsReports reports;
wu@webrtc.org97077a32013-10-25 21:18:33 +0000739
740 // Instruct the session to return stats containing the transport channel.
741 InitSessionStats(kVcName);
742 EXPECT_CALL(session_, GetStats(_))
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000743 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
744 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000745
746 // Constructs an ssrc stats update.
747 cricket::VideoMediaInfo stats_read;
748
749 cricket::SsrcReceiverInfo remote_ssrc_stats;
750 remote_ssrc_stats.timestamp = 12345.678;
751 remote_ssrc_stats.ssrc = kSsrcOfTrack;
752 cricket::VideoSenderInfo video_sender_info;
sergeyu@chromium.org5bc25c42013-12-05 00:24:06 +0000753 video_sender_info.add_ssrc(kSsrcOfTrack);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000754 video_sender_info.remote_stats.push_back(remote_ssrc_stats);
755 stats_read.senders.push_back(video_sender_info);
756
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000757 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
758 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000759 EXPECT_CALL(*media_channel, GetStats(_, _))
760 .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
wu@webrtc.org97077a32013-10-25 21:18:33 +0000761 Return(true)));
762
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000763 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000764 stats.GetStats(NULL, &reports);
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000765 const StatsReport* remote_report = FindNthReportByType(reports,
766 StatsReport::kStatsReportTypeRemoteSsrc, 1);
wu@webrtc.org97077a32013-10-25 21:18:33 +0000767 EXPECT_FALSE(remote_report == NULL);
768 EXPECT_NE(0, remote_report->timestamp);
769}
770
wu@webrtc.org4551b792013-10-09 15:37:36 +0000771// This test verifies that all chained certificates are correctly
772// reported
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000773TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000774 // Build local certificate chain.
775 std::vector<std::string> local_ders(5);
776 local_ders[0] = "These";
777 local_ders[1] = "are";
778 local_ders[2] = "some";
779 local_ders[3] = "der";
780 local_ders[4] = "values";
781 talk_base::FakeSSLCertificate local_cert(DersToPems(local_ders));
782
783 // Build remote certificate chain
784 std::vector<std::string> remote_ders(4);
785 remote_ders[0] = "A";
786 remote_ders[1] = "non-";
787 remote_ders[2] = "intersecting";
788 remote_ders[3] = "set";
789 talk_base::FakeSSLCertificate remote_cert(DersToPems(remote_ders));
790
791 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders);
792}
793
794// This test verifies that all certificates without chains are correctly
795// reported.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000796TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000797 // Build local certificate.
798 std::string local_der = "This is the local der.";
799 talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
800
801 // Build remote certificate.
802 std::string remote_der = "This is somebody else's der.";
803 talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
804
805 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
806 remote_cert, std::vector<std::string>(1, remote_der));
807}
808
809// This test verifies that the stats are generated correctly when no
810// transport is present.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000811TEST_F(StatsCollectorTest, NoTransport) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000812 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000813 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000814 stats.set_session(&session_);
815
816 // Fake stats to process.
817 cricket::TransportChannelStats channel_stats;
818 channel_stats.component = 1;
819
820 cricket::TransportStats transport_stats;
821 transport_stats.content_name = "audio";
822 transport_stats.channel_stats.push_back(channel_stats);
823
824 cricket::SessionStats session_stats;
825 session_stats.transport_stats[transport_stats.content_name] =
826 transport_stats;
827
828 // Configure MockWebRtcSession
829 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
830 .WillOnce(ReturnNull());
831 EXPECT_CALL(session_, GetStats(_))
832 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
833 Return(true)));
wu@webrtc.org97077a32013-10-25 21:18:33 +0000834
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000835 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
836 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000837
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000838 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000839 stats.GetStats(NULL, &reports);
840
841 // Check that the local certificate is absent.
842 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000843 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000844 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000845 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000846 ASSERT_EQ(kNotFound, local_certificate_id);
847
848 // Check that the remote certificate is absent.
849 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000850 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000851 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000852 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000853 ASSERT_EQ(kNotFound, remote_certificate_id);
854}
855
856// This test verifies that the stats are generated correctly when the transport
857// does not have any certificates.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000858TEST_F(StatsCollectorTest, NoCertificates) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000859 webrtc::StatsCollector stats; // Implementation under test.
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000860 StatsReports reports; // returned values.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000861 stats.set_session(&session_);
862
863 // Fake stats to process.
864 cricket::TransportChannelStats channel_stats;
865 channel_stats.component = 1;
866
867 cricket::TransportStats transport_stats;
868 transport_stats.content_name = "audio";
869 transport_stats.channel_stats.push_back(channel_stats);
870
871 cricket::SessionStats session_stats;
872 session_stats.transport_stats[transport_stats.content_name] =
873 transport_stats;
874
875 // Fake transport object.
876 talk_base::scoped_ptr<cricket::FakeTransport> transport(
877 new cricket::FakeTransport(
878 session_.signaling_thread(),
879 session_.worker_thread(),
880 transport_stats.content_name));
881
882 // Configure MockWebRtcSession
883 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
884 .WillOnce(Return(transport.get()));
885 EXPECT_CALL(session_, GetStats(_))
886 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
887 Return(true)));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000888 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
889 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.org4551b792013-10-09 15:37:36 +0000890
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000891 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000892 stats.GetStats(NULL, &reports);
893
894 // Check that the local certificate is absent.
895 std::string local_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000896 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000897 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000898 StatsReport::kStatsValueNameLocalCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000899 ASSERT_EQ(kNotFound, local_certificate_id);
900
901 // Check that the remote certificate is absent.
902 std::string remote_certificate_id = ExtractStatsValue(
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000903 StatsReport::kStatsReportTypeComponent,
wu@webrtc.org4551b792013-10-09 15:37:36 +0000904 reports,
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000905 StatsReport::kStatsValueNameRemoteCertificateId);
wu@webrtc.org4551b792013-10-09 15:37:36 +0000906 ASSERT_EQ(kNotFound, remote_certificate_id);
907}
908
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000909// This test verifies that a remote certificate with an unsupported digest
910// algorithm is correctly ignored.
911TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) {
912 // Build a local certificate.
913 std::string local_der = "This is the local der.";
914 talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
915
916 // Build a remote certificate with an unsupported digest algorithm.
917 std::string remote_der = "This is somebody else's der.";
918 talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
919 remote_cert.set_digest_algorithm("foobar");
920
921 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
922 remote_cert, std::vector<std::string>());
923}
924
925// Verifies the correct optons are passed to the VideoMediaChannel when using
926// verbose output level.
927TEST_F(StatsCollectorTest, StatsOutputLevelVerbose) {
928 webrtc::StatsCollector stats; // Implementation under test.
929 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
930 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
931 media_engine_, media_channel, &session_, "", false, NULL);
932 stats.set_session(&session_);
933
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000934 StatsReports reports; // returned values.
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000935 cricket::VideoMediaInfo stats_read;
936 cricket::BandwidthEstimationInfo bwe;
937 bwe.total_received_propagation_delta_ms = 10;
938 bwe.recent_received_propagation_delta_ms.push_back(100);
939 bwe.recent_received_propagation_delta_ms.push_back(200);
940 bwe.recent_received_packet_group_arrival_time_ms.push_back(1000);
941 bwe.recent_received_packet_group_arrival_time_ms.push_back(2000);
942 stats_read.bw_estimations.push_back(bwe);
943
944 EXPECT_CALL(session_, video_channel())
945 .WillRepeatedly(Return(&video_channel));
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000946 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
wu@webrtc.orgb9a088b2014-02-13 23:18:49 +0000947
948 StatsOptions options;
949 options.include_received_propagation_stats = true;
950 EXPECT_CALL(*media_channel, GetStats(
951 Field(&StatsOptions::include_received_propagation_stats, true),
952 _))
953 .WillOnce(DoAll(SetArgPointee<1>(stats_read),
954 Return(true)));
955
956 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelDebug);
957 stats.GetStats(NULL, &reports);
958 std::string result = ExtractBweStatsValue(
959 reports, "googReceivedPacketGroupPropagationDeltaSumDebug");
960 EXPECT_EQ("10", result);
961 result = ExtractBweStatsValue(
962 reports, "googReceivedPacketGroupPropagationDeltaDebug");
963 EXPECT_EQ("[100, 200]", result);
964 result = ExtractBweStatsValue(
965 reports, "googReceivedPacketGroupArrivalTimeDebug");
966 EXPECT_EQ("[1000, 2000]", result);
967}
968
henrike@webrtc.org40b3b682014-03-03 18:30:11 +0000969// This test verifies that a local stats object can get statistics via
970// AudioTrackInterface::GetStats() method.
971TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) {
972 webrtc::StatsCollector stats; // Implementation under test.
973 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
974 // The content_name known by the voice channel.
975 const std::string kVcName("vcname");
976 cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
977 media_engine_, media_channel, &session_, kVcName, false);
978 AddLocalAudioTrackStats();
979 stats.AddStream(stream_);
980 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
981
982 stats.set_session(&session_);
983
984 // Instruct the session to return stats containing the transport channel.
985 InitSessionStats(kVcName);
986 EXPECT_CALL(session_, GetStats(_))
987 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
988 Return(true)));
989
990 cricket::VoiceSenderInfo voice_sender_info;
991 // Contents won't be modified by the AudioTrackInterface::GetStats().
992 voice_sender_info.add_ssrc(kSsrcOfTrack);
993 voice_sender_info.codec_name = "fake_codec";
994 voice_sender_info.bytes_sent = 100;
995 voice_sender_info.packets_sent = 101;
996 voice_sender_info.rtt_ms = 102;
997 voice_sender_info.fraction_lost = 103;
998 voice_sender_info.jitter_ms = 104;
999 voice_sender_info.packets_lost = 105;
1000 voice_sender_info.ext_seqnum = 106;
1001
1002 // Contents will be modified by the AudioTrackInterface::GetStats().
1003 voice_sender_info.audio_level = 107;
1004 voice_sender_info.echo_return_loss = 108;;
1005 voice_sender_info.echo_return_loss_enhancement = 109;
1006 voice_sender_info.echo_delay_median_ms = 110;
1007 voice_sender_info.echo_delay_std_ms = 111;
1008 voice_sender_info.aec_quality_min = 112.0f;
1009 voice_sender_info.typing_noise_detected = false;
1010
1011 // Constructs an ssrc stats update.
1012 cricket::VoiceMediaInfo stats_read;
1013 stats_read.senders.push_back(voice_sender_info);
1014
1015 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
1016 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
1017 EXPECT_CALL(*media_channel, GetStats(_))
1018 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
1019 Return(true)));
1020
1021 StatsReports reports; // returned values.
1022 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1023 stats.GetStats(NULL, &reports);
1024
1025 // Verfy the existence of the track report.
1026 const StatsReport* report = FindNthReportByType(
1027 reports, StatsReport::kStatsReportTypeSsrc, 1);
1028 EXPECT_FALSE(report == NULL);
1029 std::string track_id = ExtractSsrcStatsValue(
1030 reports, StatsReport::kStatsValueNameTrackId);
1031 EXPECT_EQ(kAudioTrackId, track_id);
1032 std::string ssrc_id = ExtractSsrcStatsValue(
1033 reports, StatsReport::kStatsValueNameSsrc);
1034 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1035
1036 // Verifies the values in the track report.
1037 audio_track_->GetSignalLevel(&voice_sender_info.audio_level);
1038 webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats;
1039 audio_track_->GetAudioProcessor()->GetStats(&audio_processor_stats);
1040 voice_sender_info.typing_noise_detected =
1041 audio_processor_stats.typing_noise_detected;
1042 voice_sender_info.echo_return_loss = audio_processor_stats.echo_return_loss;
1043 voice_sender_info.echo_return_loss_enhancement =
1044 audio_processor_stats.echo_return_loss_enhancement;
1045 voice_sender_info.echo_delay_median_ms =
1046 audio_processor_stats.echo_delay_median_ms;
1047 voice_sender_info.aec_quality_min = audio_processor_stats.aec_quality_min;
1048 voice_sender_info.echo_delay_std_ms = audio_processor_stats.echo_delay_std_ms;
1049 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1050
1051 // Verify we get the same result by passing a track to GetStats().
1052 StatsReports track_reports; // returned values.
1053 stats.GetStats(audio_track_.get(), &track_reports);
1054 const StatsReport* track_report = FindNthReportByType(
1055 track_reports, StatsReport::kStatsReportTypeSsrc, 1);
1056 EXPECT_FALSE(track_report == NULL);
1057 track_id = ExtractSsrcStatsValue(track_reports,
1058 StatsReport::kStatsValueNameTrackId);
1059 EXPECT_EQ(kAudioTrackId, track_id);
1060 ssrc_id = ExtractSsrcStatsValue(track_reports,
1061 StatsReport::kStatsValueNameSsrc);
1062 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1063 VerifyVoiceSenderInfoReport(track_report, voice_sender_info);
1064}
1065
1066// This test verifies that a local stats object won't update its statistics
1067// after a RemoveLocalAudioTrack() call.
1068TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) {
1069 webrtc::StatsCollector stats; // Implementation under test.
1070 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel();
1071 // The content_name known by the voice channel.
1072 const std::string kVcName("vcname");
1073 cricket::VoiceChannel voice_channel(talk_base::Thread::Current(),
1074 media_engine_, media_channel, &session_, kVcName, false);
1075 AddLocalAudioTrackStats();
1076 stats.AddStream(stream_);
1077 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1078
1079 stats.set_session(&session_);
1080
1081 // Instruct the session to return stats containing the transport channel.
1082 InitSessionStats(kVcName);
1083 EXPECT_CALL(session_, GetStats(_))
1084 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
1085 Return(true)));
1086
1087 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack);
1088 cricket::VoiceSenderInfo voice_sender_info;
1089 // Contents won't be modified by the AudioTrackInterface::GetStats().
1090 voice_sender_info.add_ssrc(kSsrcOfTrack);
1091 voice_sender_info.codec_name = "fake_codec";
1092 voice_sender_info.bytes_sent = 100;
1093 voice_sender_info.packets_sent = 101;
1094 voice_sender_info.rtt_ms = 102;
1095 voice_sender_info.fraction_lost = 103;
1096 voice_sender_info.jitter_ms = 104;
1097 voice_sender_info.packets_lost = 105;
1098 voice_sender_info.ext_seqnum = 106;
1099
1100 // Contents will be modified by the AudioTrackInterface::GetStats().
1101 voice_sender_info.audio_level = 107;
1102 voice_sender_info.echo_return_loss = 108;;
1103 voice_sender_info.echo_return_loss_enhancement = 109;
1104 voice_sender_info.echo_delay_median_ms = 110;
1105 voice_sender_info.echo_delay_std_ms = 111;
1106 voice_sender_info.aec_quality_min = 112;
1107 voice_sender_info.typing_noise_detected = false;
1108
1109 // Constructs an ssrc stats update.
1110 cricket::VoiceMediaInfo stats_read;
1111 stats_read.senders.push_back(voice_sender_info);
1112
1113 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel));
1114 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
1115 EXPECT_CALL(*media_channel, GetStats(_))
1116 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
1117 Return(true)));
1118
1119 StatsReports reports; // returned values.
1120 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
1121 stats.GetStats(NULL, &reports);
1122
1123 // The report will exist since we don't remove them in RemoveStream().
1124 const StatsReport* report = FindNthReportByType(
1125 reports, StatsReport::kStatsReportTypeSsrc, 1);
1126 EXPECT_FALSE(report == NULL);
1127 std::string track_id = ExtractSsrcStatsValue(
1128 reports, StatsReport::kStatsValueNameTrackId);
1129 EXPECT_EQ(kAudioTrackId, track_id);
1130 std::string ssrc_id = ExtractSsrcStatsValue(
1131 reports, StatsReport::kStatsValueNameSsrc);
1132 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
1133
1134 // Verifies the values in the track report, no value will be changed by the
1135 // AudioTrackInterface::GetSignalValue() and
1136 // AudioProcessorInterface::AudioProcessorStats::GetStats();
1137 VerifyVoiceSenderInfoReport(report, voice_sender_info);
1138}
1139
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140} // namespace