blob: d9cde5d83a288019eabaf1266c6cca9628dba7ce [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"
32#include "talk/app/webrtc/videotrack.h"
wu@webrtc.org4551b792013-10-09 15:37:36 +000033#include "talk/base/base64.h"
34#include "talk/base/fakesslidentity.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035#include "talk/base/gunit.h"
36#include "talk/media/base/fakemediaengine.h"
37#include "talk/media/devices/fakedevicemanager.h"
38#include "talk/p2p/base/fakesession.h"
39#include "talk/session/media/channelmanager.h"
40#include "testing/base/public/gmock.h"
41
42using testing::_;
43using testing::DoAll;
44using testing::Return;
45using testing::ReturnNull;
46using testing::SetArgPointee;
47
48namespace cricket {
49
50class ChannelManager;
51class FakeDeviceManager;
52
53} // namespace cricket
54
55namespace {
56
57// Error return values
58const char kNotFound[] = "NOT FOUND";
59const char kNoReports[] = "NO REPORTS";
60
61class MockWebRtcSession : public webrtc::WebRtcSession {
62 public:
63 explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
64 : WebRtcSession(channel_manager, talk_base::Thread::Current(),
wu@webrtc.org4551b792013-10-09 15:37:36 +000065 talk_base::Thread::Current(), NULL, NULL) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 }
67 MOCK_METHOD0(video_channel, cricket::VideoChannel*());
68 MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
69 MOCK_METHOD1(GetStats, bool(cricket::SessionStats*));
wu@webrtc.org4551b792013-10-09 15:37:36 +000070 MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&));
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071};
72
73class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
74 public:
75 MockVideoMediaChannel()
76 : cricket::FakeVideoMediaChannel(NULL) {
77 }
78 // MOCK_METHOD0(transport_channel, cricket::TransportChannel*());
79 MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*));
80};
81
wu@webrtc.org4551b792013-10-09 15:37:36 +000082bool GetValue(const webrtc::StatsReport* report,
83 const std::string& name,
84 std::string* value) {
85 webrtc::StatsReport::Values::const_iterator it = report->values.begin();
86 for (; it != report->values.end(); ++it) {
87 if (it->name == name) {
88 *value = it->value;
89 return true;
90 }
91 }
92 return false;
93}
94
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095std::string ExtractStatsValue(const std::string& type,
wu@webrtc.org4551b792013-10-09 15:37:36 +000096 const webrtc::StatsReports& reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097 const std::string name) {
98 if (reports.empty()) {
99 return kNoReports;
100 }
101 for (size_t i = 0; i < reports.size(); ++i) {
102 if (reports[i].type != type)
103 continue;
wu@webrtc.org4551b792013-10-09 15:37:36 +0000104 std::string ret;
105 if (GetValue(&reports[i], name, &ret)) {
106 return ret;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107 }
108 }
109
110 return kNotFound;
111}
112
113// Finds the |n|-th report of type |type| in |reports|.
114// |n| starts from 1 for finding the first report.
wu@webrtc.org4551b792013-10-09 15:37:36 +0000115const webrtc::StatsReport* FindNthReportByType(
116 const webrtc::StatsReports& reports, const std::string& type, int n) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117 for (size_t i = 0; i < reports.size(); ++i) {
118 if (reports[i].type == type) {
119 n--;
120 if (n == 0)
121 return &reports[i];
122 }
123 }
124 return NULL;
125}
126
wu@webrtc.org4551b792013-10-09 15:37:36 +0000127const webrtc::StatsReport* FindReportById(const webrtc::StatsReports& reports,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000128 const std::string& id) {
129 for (size_t i = 0; i < reports.size(); ++i) {
130 if (reports[i].id == id) {
131 return &reports[i];
132 }
133 }
134 return NULL;
135}
136
137std::string ExtractSsrcStatsValue(webrtc::StatsReports reports,
138 const std::string& name) {
139 return ExtractStatsValue(
140 webrtc::StatsReport::kStatsReportTypeSsrc, reports, name);
141}
142
143std::string ExtractBweStatsValue(webrtc::StatsReports reports,
144 const std::string& name) {
145 return ExtractStatsValue(
146 webrtc::StatsReport::kStatsReportTypeBwe, reports, name);
147}
148
wu@webrtc.org4551b792013-10-09 15:37:36 +0000149std::string DerToPem(const std::string& der) {
150 return talk_base::SSLIdentity::DerToPem(
151 talk_base::kPemTypeCertificate,
152 reinterpret_cast<const unsigned char*>(der.c_str()),
153 der.length());
154}
155
156std::vector<std::string> DersToPems(
157 const std::vector<std::string>& ders) {
158 std::vector<std::string> pems(ders.size());
159 std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem);
160 return pems;
161}
162
163void CheckCertChainReports(const webrtc::StatsReports& reports,
164 const std::vector<std::string>& ders,
165 const std::string& start_id) {
166 std::string certificate_id = start_id;
167 size_t i = 0;
168 while (true) {
169 const webrtc::StatsReport* report = FindReportById(reports, certificate_id);
170 ASSERT_TRUE(report != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000171
wu@webrtc.org4551b792013-10-09 15:37:36 +0000172 std::string der_base64;
173 EXPECT_TRUE(GetValue(
174 report, webrtc::StatsReport::kStatsValueNameDer, &der_base64));
175 std::string der = talk_base::Base64::Decode(der_base64,
176 talk_base::Base64::DO_STRICT);
177 EXPECT_EQ(ders[i], der);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000178
179 std::string fingerprint_algorithm;
180 EXPECT_TRUE(GetValue(
181 report,
182 webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
183 &fingerprint_algorithm));
184 // The digest algorithm for a FakeSSLCertificate is always SHA-1.
185 std::string sha_1_str = talk_base::DIGEST_SHA_1;
186 EXPECT_EQ(sha_1_str, fingerprint_algorithm);
187
188 std::string dummy_fingerprint; // Value is not checked.
189 EXPECT_TRUE(GetValue(
190 report,
191 webrtc::StatsReport::kStatsValueNameFingerprint,
192 &dummy_fingerprint));
193
wu@webrtc.org4551b792013-10-09 15:37:36 +0000194 ++i;
195 if (!GetValue(
196 report, webrtc::StatsReport::kStatsValueNameIssuerId, &certificate_id))
197 break;
198 }
199 EXPECT_EQ(ders.size(), i);
200}
201
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000202class StatsCollectorTest : public testing::Test {
203 protected:
204 StatsCollectorTest()
205 : media_engine_(new cricket::FakeMediaEngine),
206 channel_manager_(
207 new cricket::ChannelManager(media_engine_,
208 new cricket::FakeDeviceManager(),
209 talk_base::Thread::Current())),
210 session_(channel_manager_.get()) {
211 // By default, we ignore session GetStats calls.
212 EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
213 }
214
wu@webrtc.org4551b792013-10-09 15:37:36 +0000215 void TestCertificateReports(const talk_base::FakeSSLCertificate& local_cert,
216 const std::vector<std::string>& local_ders,
217 const talk_base::FakeSSLCertificate& remote_cert,
218 const std::vector<std::string>& remote_ders) {
219 webrtc::StatsCollector stats; // Implementation under test.
220 webrtc::StatsReports reports; // returned values.
221 stats.set_session(&session_);
222
223 // Fake stats to process.
224 cricket::TransportChannelStats channel_stats;
225 channel_stats.component = 1;
226
227 cricket::TransportStats transport_stats;
228 transport_stats.content_name = "audio";
229 transport_stats.channel_stats.push_back(channel_stats);
230
231 cricket::SessionStats session_stats;
232 session_stats.transport_stats[transport_stats.content_name] =
233 transport_stats;
234
235 // Fake certificates to report.
236 talk_base::FakeSSLIdentity local_identity(local_cert);
237 talk_base::scoped_ptr<talk_base::FakeSSLCertificate> remote_cert_copy(
238 remote_cert.GetReference());
239
240 // Fake transport object.
241 talk_base::scoped_ptr<cricket::FakeTransport> transport(
242 new cricket::FakeTransport(
243 session_.signaling_thread(),
244 session_.worker_thread(),
245 transport_stats.content_name));
246 transport->SetIdentity(&local_identity);
247 cricket::FakeTransportChannel* channel =
248 static_cast<cricket::FakeTransportChannel*>(
249 transport->CreateChannel(channel_stats.component));
250 EXPECT_FALSE(channel == NULL);
251 channel->SetRemoteCertificate(remote_cert_copy.get());
252
253 // Configure MockWebRtcSession
254 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
255 .WillOnce(Return(transport.get()));
256 EXPECT_CALL(session_, GetStats(_))
257 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
258 Return(true)));
259 EXPECT_CALL(session_, video_channel())
260 .WillRepeatedly(ReturnNull());
261
262 stats.UpdateStats();
263
264 stats.GetStats(NULL, &reports);
265
266 const webrtc::StatsReport* channel_report = FindNthReportByType(
267 reports, webrtc::StatsReport::kStatsReportTypeComponent, 1);
268 EXPECT_TRUE(channel_report != NULL);
269
270 // Check local certificate chain.
271 std::string local_certificate_id = ExtractStatsValue(
272 webrtc::StatsReport::kStatsReportTypeComponent,
273 reports,
274 webrtc::StatsReport::kStatsValueNameLocalCertificateId);
275 EXPECT_NE(kNotFound, local_certificate_id);
276 CheckCertChainReports(reports, local_ders, local_certificate_id);
277
278 // Check remote certificate chain.
279 std::string remote_certificate_id = ExtractStatsValue(
280 webrtc::StatsReport::kStatsReportTypeComponent,
281 reports,
282 webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
283 EXPECT_NE(kNotFound, remote_certificate_id);
284 CheckCertChainReports(reports, remote_ders, remote_certificate_id);
285 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 cricket::FakeMediaEngine* media_engine_;
287 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
288 MockWebRtcSession session_;
289};
290
291// This test verifies that 64-bit counters are passed successfully.
292TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) {
293 webrtc::StatsCollector stats; // Implementation under test.
294 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
295 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
296 media_engine_, media_channel, &session_, "", false, NULL);
297 webrtc::StatsReports reports; // returned values.
298 cricket::VideoSenderInfo video_sender_info;
299 cricket::VideoMediaInfo stats_read;
300 const uint32 kSsrcOfTrack = 1234;
301 const std::string kNameOfTrack("somename");
302 // The number of bytes must be larger than 0xFFFFFFFF for this test.
303 const int64 kBytesSent = 12345678901234LL;
304 const std::string kBytesSentString("12345678901234");
305
306 stats.set_session(&session_);
307 talk_base::scoped_refptr<webrtc::MediaStream> stream(
308 webrtc::MediaStream::Create("streamlabel"));
309 stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
310 stats.AddStream(stream);
311
312 // Construct a stats value to read.
313 video_sender_info.ssrcs.push_back(1234);
314 video_sender_info.bytes_sent = kBytesSent;
315 stats_read.senders.push_back(video_sender_info);
316
317 EXPECT_CALL(session_, video_channel())
318 .WillRepeatedly(Return(&video_channel));
319 EXPECT_CALL(*media_channel, GetStats(_))
320 .WillOnce(DoAll(SetArgPointee<0>(stats_read),
321 Return(true)));
322 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
323 .WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
324 Return(true)));
325 stats.UpdateStats();
326 stats.GetStats(NULL, &reports);
327 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
328 EXPECT_EQ(kBytesSentString, result);
329}
330
331// Test that BWE information is reported via stats.
332TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) {
333 webrtc::StatsCollector stats; // Implementation under test.
334 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
335 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
336 media_engine_, media_channel, &session_, "", false, NULL);
337 webrtc::StatsReports reports; // returned values.
338 cricket::VideoSenderInfo video_sender_info;
339 cricket::VideoMediaInfo stats_read;
340 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and
341 // BWE.
342 const uint32 kSsrcOfTrack = 1234;
343 const std::string kNameOfTrack("somename");
344 const int64 kBytesSent = 12345678901234LL;
345 const std::string kBytesSentString("12345678901234");
346
347 stats.set_session(&session_);
348 talk_base::scoped_refptr<webrtc::MediaStream> stream(
349 webrtc::MediaStream::Create("streamlabel"));
350 stream->AddTrack(webrtc::VideoTrack::Create(kNameOfTrack, NULL));
351 stats.AddStream(stream);
352
353 // Construct a stats value to read.
354 video_sender_info.ssrcs.push_back(1234);
355 video_sender_info.bytes_sent = kBytesSent;
356 stats_read.senders.push_back(video_sender_info);
357 cricket::BandwidthEstimationInfo bwe;
358 const int kTargetEncBitrate = 123456;
359 const std::string kTargetEncBitrateString("123456");
360 bwe.target_enc_bitrate = kTargetEncBitrate;
361 stats_read.bw_estimations.push_back(bwe);
362
363 EXPECT_CALL(session_, video_channel())
364 .WillRepeatedly(Return(&video_channel));
365 EXPECT_CALL(*media_channel, GetStats(_))
366 .WillOnce(DoAll(SetArgPointee<0>(stats_read),
367 Return(true)));
368 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
369 .WillOnce(DoAll(SetArgPointee<1>(kNameOfTrack),
370 Return(true)));
371 stats.UpdateStats();
372 stats.GetStats(NULL, &reports);
373 std::string result = ExtractSsrcStatsValue(reports, "bytesSent");
374 EXPECT_EQ(kBytesSentString, result);
375 result = ExtractBweStatsValue(reports, "googTargetEncBitrate");
376 EXPECT_EQ(kTargetEncBitrateString, result);
377}
378
379// This test verifies that an object of type "googSession" always
380// exists in the returned stats.
381TEST_F(StatsCollectorTest, SessionObjectExists) {
382 webrtc::StatsCollector stats; // Implementation under test.
383 webrtc::StatsReports reports; // returned values.
384 stats.set_session(&session_);
385 EXPECT_CALL(session_, video_channel())
386 .WillRepeatedly(ReturnNull());
387 stats.UpdateStats();
388 stats.GetStats(NULL, &reports);
389 const webrtc::StatsReport* session_report = FindNthReportByType(
390 reports, webrtc::StatsReport::kStatsReportTypeSession, 1);
391 EXPECT_FALSE(session_report == NULL);
392}
393
394// This test verifies that only one object of type "googSession" exists
395// in the returned stats.
396TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
397 webrtc::StatsCollector stats; // Implementation under test.
398 webrtc::StatsReports reports; // returned values.
399 stats.set_session(&session_);
400 EXPECT_CALL(session_, video_channel())
401 .WillRepeatedly(ReturnNull());
402 stats.UpdateStats();
403 stats.UpdateStats();
404 stats.GetStats(NULL, &reports);
405 const webrtc::StatsReport* session_report = FindNthReportByType(
406 reports, webrtc::StatsReport::kStatsReportTypeSession, 1);
407 EXPECT_FALSE(session_report == NULL);
408 session_report = FindNthReportByType(
409 reports, webrtc::StatsReport::kStatsReportTypeSession, 2);
410 EXPECT_EQ(NULL, session_report);
411}
412
413// This test verifies that the empty track report exists in the returned stats
414// without calling StatsCollector::UpdateStats.
415TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) {
416 webrtc::StatsCollector stats; // Implementation under test.
417 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
418 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
419 media_engine_, media_channel, &session_, "", false, NULL);
420 const std::string kTrackId("somename");
421 talk_base::scoped_refptr<webrtc::MediaStream> stream(
422 webrtc::MediaStream::Create("streamlabel"));
423 talk_base::scoped_refptr<webrtc::VideoTrack> track =
424 webrtc::VideoTrack::Create(kTrackId, NULL);
425 stream->AddTrack(track);
426 stats.AddStream(stream);
427
428 stats.set_session(&session_);
429
430 webrtc::StatsReports reports;
431
432 // Verfies the existence of the track report.
433 stats.GetStats(NULL, &reports);
434 EXPECT_EQ((size_t)1, reports.size());
435 EXPECT_EQ(std::string(webrtc::StatsReport::kStatsReportTypeTrack),
436 reports[0].type);
437
438 std::string trackValue =
439 ExtractStatsValue(webrtc::StatsReport::kStatsReportTypeTrack,
440 reports,
441 webrtc::StatsReport::kStatsValueNameTrackId);
442 EXPECT_EQ(kTrackId, trackValue);
443}
444
445// This test verifies that the empty track report exists in the returned stats
446// when StatsCollector::UpdateStats is called with ssrc stats.
447TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) {
448 webrtc::StatsCollector stats; // Implementation under test.
449 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
450 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
451 media_engine_, media_channel, &session_, "", false, NULL);
452 const std::string kTrackId("somename");
453 talk_base::scoped_refptr<webrtc::MediaStream> stream(
454 webrtc::MediaStream::Create("streamlabel"));
455 talk_base::scoped_refptr<webrtc::VideoTrack> track =
456 webrtc::VideoTrack::Create(kTrackId, NULL);
457 stream->AddTrack(track);
458 stats.AddStream(stream);
459
460 stats.set_session(&session_);
461
462 webrtc::StatsReports reports;
463
464 // Constructs an ssrc stats update.
465 cricket::VideoSenderInfo video_sender_info;
466 cricket::VideoMediaInfo stats_read;
467 const uint32 kSsrcOfTrack = 1234;
468 const int64 kBytesSent = 12345678901234LL;
469
470 // Construct a stats value to read.
471 video_sender_info.ssrcs.push_back(1234);
472 video_sender_info.bytes_sent = kBytesSent;
473 stats_read.senders.push_back(video_sender_info);
474
475 EXPECT_CALL(session_, video_channel())
476 .WillRepeatedly(Return(&video_channel));
477 EXPECT_CALL(*media_channel, GetStats(_))
478 .WillOnce(DoAll(SetArgPointee<0>(stats_read),
479 Return(true)));
480 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
481 .WillOnce(DoAll(SetArgPointee<1>(kTrackId),
482 Return(true)));
483
484 stats.UpdateStats();
485 stats.GetStats(NULL, &reports);
486 // |reports| should contain one session report, one track report, and one ssrc
487 // report.
488 EXPECT_EQ((size_t)3, reports.size());
489 const webrtc::StatsReport* track_report = FindNthReportByType(
490 reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
491 EXPECT_FALSE(track_report == NULL);
492
493 stats.GetStats(track, &reports);
494 // |reports| should contain one session report, one track report, and one ssrc
495 // report.
496 EXPECT_EQ((size_t)3, reports.size());
497 track_report = FindNthReportByType(
498 reports, webrtc::StatsReport::kStatsReportTypeTrack, 1);
499 EXPECT_FALSE(track_report == NULL);
500
501 std::string ssrc_id = ExtractSsrcStatsValue(
502 reports, webrtc::StatsReport::kStatsValueNameSsrc);
503 EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
504
505 std::string track_id = ExtractSsrcStatsValue(
506 reports, webrtc::StatsReport::kStatsValueNameTrackId);
507 EXPECT_EQ(kTrackId, track_id);
508}
509
510// This test verifies that an SSRC object has the identifier of a Transport
511// stats object, and that this transport stats object exists in stats.
512TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) {
513 webrtc::StatsCollector stats; // Implementation under test.
514 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel;
515 // The content_name known by the video channel.
516 const std::string kVcName("vcname");
517 cricket::VideoChannel video_channel(talk_base::Thread::Current(),
518 media_engine_, media_channel, &session_, kVcName, false, NULL);
519 const std::string kTrackId("somename");
520 talk_base::scoped_refptr<webrtc::MediaStream> stream(
521 webrtc::MediaStream::Create("streamlabel"));
522 talk_base::scoped_refptr<webrtc::VideoTrack> track =
523 webrtc::VideoTrack::Create(kTrackId, NULL);
524 stream->AddTrack(track);
525 stats.AddStream(stream);
526
527 stats.set_session(&session_);
528
529 webrtc::StatsReports reports;
530
531 // Constructs an ssrc stats update.
532 cricket::VideoSenderInfo video_sender_info;
533 cricket::VideoMediaInfo stats_read;
534 const uint32 kSsrcOfTrack = 1234;
535 const int64 kBytesSent = 12345678901234LL;
536
537 // Construct a stats value to read.
538 video_sender_info.ssrcs.push_back(1234);
539 video_sender_info.bytes_sent = kBytesSent;
540 stats_read.senders.push_back(video_sender_info);
541
542 EXPECT_CALL(session_, video_channel())
543 .WillRepeatedly(Return(&video_channel));
544 EXPECT_CALL(*media_channel, GetStats(_))
545 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read),
546 Return(true)));
547 EXPECT_CALL(session_, GetTrackIdBySsrc(kSsrcOfTrack, _))
548 .WillOnce(DoAll(SetArgPointee<1>(kTrackId),
549 Return(true)));
550
551 // Instruct the session to return stats containing the transport channel.
552 const std::string kTransportName("trspname");
553 cricket::SessionStats session_stats;
554 cricket::TransportStats transport_stats;
555 cricket::TransportChannelStats channel_stats;
556 channel_stats.component = 1;
557 transport_stats.content_name = kTransportName;
558 transport_stats.channel_stats.push_back(channel_stats);
559
560 session_stats.transport_stats[kTransportName] = transport_stats;
561 session_stats.proxy_to_transport[kVcName] = kTransportName;
562 EXPECT_CALL(session_, GetStats(_))
563 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats),
564 Return(true)));
565
566 stats.UpdateStats();
567 stats.GetStats(NULL, &reports);
568 std::string transport_id = ExtractStatsValue(
569 webrtc::StatsReport::kStatsReportTypeSsrc,
570 reports,
571 webrtc::StatsReport::kStatsValueNameTransportId);
572 ASSERT_NE(kNotFound, transport_id);
573 const webrtc::StatsReport* transport_report = FindReportById(reports,
574 transport_id);
575 ASSERT_FALSE(transport_report == NULL);
576}
577
wu@webrtc.org4551b792013-10-09 15:37:36 +0000578// This test verifies that all chained certificates are correctly
579// reported
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000580TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000581 // Build local certificate chain.
582 std::vector<std::string> local_ders(5);
583 local_ders[0] = "These";
584 local_ders[1] = "are";
585 local_ders[2] = "some";
586 local_ders[3] = "der";
587 local_ders[4] = "values";
588 talk_base::FakeSSLCertificate local_cert(DersToPems(local_ders));
589
590 // Build remote certificate chain
591 std::vector<std::string> remote_ders(4);
592 remote_ders[0] = "A";
593 remote_ders[1] = "non-";
594 remote_ders[2] = "intersecting";
595 remote_ders[3] = "set";
596 talk_base::FakeSSLCertificate remote_cert(DersToPems(remote_ders));
597
598 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders);
599}
600
601// This test verifies that all certificates without chains are correctly
602// reported.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000603TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000604 // Build local certificate.
605 std::string local_der = "This is the local der.";
606 talk_base::FakeSSLCertificate local_cert(DerToPem(local_der));
607
608 // Build remote certificate.
609 std::string remote_der = "This is somebody else's der.";
610 talk_base::FakeSSLCertificate remote_cert(DerToPem(remote_der));
611
612 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der),
613 remote_cert, std::vector<std::string>(1, remote_der));
614}
615
616// This test verifies that the stats are generated correctly when no
617// transport is present.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000618TEST_F(StatsCollectorTest, NoTransport) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000619 webrtc::StatsCollector stats; // Implementation under test.
620 webrtc::StatsReports reports; // returned values.
621 stats.set_session(&session_);
622
623 // Fake stats to process.
624 cricket::TransportChannelStats channel_stats;
625 channel_stats.component = 1;
626
627 cricket::TransportStats transport_stats;
628 transport_stats.content_name = "audio";
629 transport_stats.channel_stats.push_back(channel_stats);
630
631 cricket::SessionStats session_stats;
632 session_stats.transport_stats[transport_stats.content_name] =
633 transport_stats;
634
635 // Configure MockWebRtcSession
636 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
637 .WillOnce(ReturnNull());
638 EXPECT_CALL(session_, GetStats(_))
639 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
640 Return(true)));
641 EXPECT_CALL(session_, video_channel())
642 .WillRepeatedly(ReturnNull());
643
644 stats.UpdateStats();
645 stats.GetStats(NULL, &reports);
646
647 // Check that the local certificate is absent.
648 std::string local_certificate_id = ExtractStatsValue(
649 webrtc::StatsReport::kStatsReportTypeComponent,
650 reports,
651 webrtc::StatsReport::kStatsValueNameLocalCertificateId);
652 ASSERT_EQ(kNotFound, local_certificate_id);
653
654 // Check that the remote certificate is absent.
655 std::string remote_certificate_id = ExtractStatsValue(
656 webrtc::StatsReport::kStatsReportTypeComponent,
657 reports,
658 webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
659 ASSERT_EQ(kNotFound, remote_certificate_id);
660}
661
662// This test verifies that the stats are generated correctly when the transport
663// does not have any certificates.
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000664TEST_F(StatsCollectorTest, NoCertificates) {
wu@webrtc.org4551b792013-10-09 15:37:36 +0000665 webrtc::StatsCollector stats; // Implementation under test.
666 webrtc::StatsReports reports; // returned values.
667 stats.set_session(&session_);
668
669 // Fake stats to process.
670 cricket::TransportChannelStats channel_stats;
671 channel_stats.component = 1;
672
673 cricket::TransportStats transport_stats;
674 transport_stats.content_name = "audio";
675 transport_stats.channel_stats.push_back(channel_stats);
676
677 cricket::SessionStats session_stats;
678 session_stats.transport_stats[transport_stats.content_name] =
679 transport_stats;
680
681 // Fake transport object.
682 talk_base::scoped_ptr<cricket::FakeTransport> transport(
683 new cricket::FakeTransport(
684 session_.signaling_thread(),
685 session_.worker_thread(),
686 transport_stats.content_name));
687
688 // Configure MockWebRtcSession
689 EXPECT_CALL(session_, GetTransport(transport_stats.content_name))
690 .WillOnce(Return(transport.get()));
691 EXPECT_CALL(session_, GetStats(_))
692 .WillOnce(DoAll(SetArgPointee<0>(session_stats),
693 Return(true)));
694 EXPECT_CALL(session_, video_channel())
695 .WillRepeatedly(ReturnNull());
696
697 stats.UpdateStats();
698 stats.GetStats(NULL, &reports);
699
700 // Check that the local certificate is absent.
701 std::string local_certificate_id = ExtractStatsValue(
702 webrtc::StatsReport::kStatsReportTypeComponent,
703 reports,
704 webrtc::StatsReport::kStatsValueNameLocalCertificateId);
705 ASSERT_EQ(kNotFound, local_certificate_id);
706
707 // Check that the remote certificate is absent.
708 std::string remote_certificate_id = ExtractStatsValue(
709 webrtc::StatsReport::kStatsReportTypeComponent,
710 reports,
711 webrtc::StatsReport::kStatsValueNameRemoteCertificateId);
712 ASSERT_EQ(kNotFound, remote_certificate_id);
713}
714
715
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716} // namespace