Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / app / webrtc / statscollector_unittest.cc
1 /*
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/mediastreaminterface.h"
33 #include "talk/app/webrtc/mediastreamtrack.h"
34 #include "talk/app/webrtc/videotrack.h"
35 #include "talk/base/base64.h"
36 #include "talk/base/fakesslidentity.h"
37 #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
44 using cricket::StatsOptions;
45 using testing::_;
46 using testing::DoAll;
47 using testing::Field;
48 using testing::Return;
49 using testing::ReturnNull;
50 using testing::SetArgPointee;
51 using webrtc::PeerConnectionInterface;
52 using webrtc::StatsReport;
53 using webrtc::StatsReports;
54
55 namespace cricket {
56
57 class ChannelManager;
58 class FakeDeviceManager;
59
60 }  // namespace cricket
61
62 namespace {
63
64 // Error return values
65 const char kNotFound[] = "NOT FOUND";
66 const char kNoReports[] = "NO REPORTS";
67
68 // Constant names for track identification.
69 const char kTrackId[] = "somename";
70 const char kAudioTrackId[] = "audio_track_id";
71 const uint32 kSsrcOfTrack = 1234;
72
73 class MockWebRtcSession : public webrtc::WebRtcSession {
74  public:
75   explicit MockWebRtcSession(cricket::ChannelManager* channel_manager)
76     : WebRtcSession(channel_manager, talk_base::Thread::Current(),
77                     talk_base::Thread::Current(), NULL, NULL) {
78   }
79   MOCK_METHOD0(voice_channel, cricket::VoiceChannel*());
80   MOCK_METHOD0(video_channel, cricket::VideoChannel*());
81   MOCK_METHOD2(GetTrackIdBySsrc, bool(uint32, std::string*));
82   MOCK_METHOD1(GetStats, bool(cricket::SessionStats*));
83   MOCK_METHOD1(GetTransport, cricket::Transport*(const std::string&));
84 };
85
86 class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel {
87  public:
88   MockVideoMediaChannel()
89     : cricket::FakeVideoMediaChannel(NULL) {
90   }
91   // MOCK_METHOD0(transport_channel, cricket::TransportChannel*());
92   MOCK_METHOD2(GetStats, bool(const StatsOptions&, cricket::VideoMediaInfo*));
93 };
94
95 class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel {
96  public:
97   MockVoiceMediaChannel() : cricket::FakeVoiceMediaChannel(NULL) {
98   }
99   MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*));
100 };
101
102 class 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
119 class 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 talk_base::scoped_refptr<webrtc::AudioProcessorInterface>
138       GetAudioProcessor() OVERRIDE {
139     return processor_;
140   }
141
142  private:
143   talk_base::scoped_refptr<FakeAudioProcessor> processor_;
144 };
145
146 bool GetValue(const StatsReport* report,
147               const std::string& name,
148               std::string* value) {
149   StatsReport::Values::const_iterator it = report->values.begin();
150   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
159 std::string ExtractStatsValue(const std::string& type,
160                               const StatsReports& reports,
161                               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;
168     std::string ret;
169     if (GetValue(&reports[i], name, &ret)) {
170       return ret;
171     }
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.
179 const StatsReport* FindNthReportByType(
180     const StatsReports& reports, const std::string& type, int n) {
181   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
191 const StatsReport* FindReportById(const StatsReports& reports,
192                                   const std::string& id) {
193   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
201 std::string ExtractSsrcStatsValue(StatsReports reports,
202                                   const std::string& name) {
203   return ExtractStatsValue(
204       StatsReport::kStatsReportTypeSsrc, reports, name);
205 }
206
207 std::string ExtractBweStatsValue(StatsReports reports,
208                                   const std::string& name) {
209   return ExtractStatsValue(
210       StatsReport::kStatsReportTypeBwe, reports, name);
211 }
212
213 std::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
220 std::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
227 void CheckCertChainReports(const StatsReports& reports,
228                            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) {
233     const StatsReport* report = FindReportById(reports, certificate_id);
234     ASSERT_TRUE(report != NULL);
235
236     std::string der_base64;
237     EXPECT_TRUE(GetValue(
238         report, StatsReport::kStatsValueNameDer, &der_base64));
239     std::string der = talk_base::Base64::Decode(der_base64,
240                                                 talk_base::Base64::DO_STRICT);
241     EXPECT_EQ(ders[i], der);
242
243     std::string fingerprint_algorithm;
244     EXPECT_TRUE(GetValue(
245         report,
246         StatsReport::kStatsValueNameFingerprintAlgorithm,
247         &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,
255         StatsReport::kStatsValueNameFingerprint,
256         &dummy_fingerprint));
257
258     ++i;
259     if (!GetValue(
260         report, StatsReport::kStatsValueNameIssuerId, &certificate_id))
261       break;
262   }
263   EXPECT_EQ(ders.size(), i);
264 }
265
266 void 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(
279       report, StatsReport::kStatsValueNamePacketsLost, &value_in_report));
280   EXPECT_EQ(talk_base::ToString<int>(sinfo.packets_lost), value_in_report);
281   EXPECT_TRUE(GetValue(
282       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
320 class 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())),
328       session_(channel_manager_.get()),
329       track_id_(kTrackId) {
330     // By default, we ignore session GetStats calls.
331     EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Return(false));
332   }
333
334   // 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
359   // 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
372   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.
377     StatsReports reports;  // returned values.
378     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)));
416     EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
417     EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
418
419     stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
420
421     stats.GetStats(NULL, &reports);
422
423     const StatsReport* channel_report = FindNthReportByType(
424         reports, StatsReport::kStatsReportTypeComponent, 1);
425     EXPECT_TRUE(channel_report != NULL);
426
427     // Check local certificate chain.
428     std::string local_certificate_id = ExtractStatsValue(
429         StatsReport::kStatsReportTypeComponent,
430         reports,
431         StatsReport::kStatsValueNameLocalCertificateId);
432     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     }
438
439     // Check remote certificate chain.
440     std::string remote_certificate_id = ExtractStatsValue(
441         StatsReport::kStatsReportTypeComponent,
442         reports,
443         StatsReport::kStatsValueNameRemoteCertificateId);
444     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     }
450   }
451
452   cricket::FakeMediaEngine* media_engine_;
453   talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
454   MockWebRtcSession session_;
455   cricket::SessionStats session_stats_;
456   talk_base::scoped_refptr<webrtc::MediaStream> stream_;
457   talk_base::scoped_refptr<webrtc::VideoTrack> track_;
458   talk_base::scoped_refptr<FakeLocalAudioTrack> audio_track_;
459   std::string track_id_;
460 };
461
462 // This test verifies that 64-bit counters are passed successfully.
463 TEST_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);
468   StatsReports reports;  // returned values.
469   cricket::VideoSenderInfo video_sender_info;
470   cricket::VideoMediaInfo stats_read;
471   // 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_);
476   AddVideoTrackStats();
477   stats.AddStream(stream_);
478
479   // Construct a stats value to read.
480   video_sender_info.add_ssrc(1234);
481   video_sender_info.bytes_sent = kBytesSent;
482   stats_read.senders.push_back(video_sender_info);
483
484   EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
485   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
486   EXPECT_CALL(*media_channel, GetStats(_, _))
487     .WillOnce(DoAll(SetArgPointee<1>(stats_read),
488                     Return(true)));
489   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
490   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.
496 TEST_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);
501   StatsReports reports;  // returned values.
502   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.
506   const int64 kBytesSent = 12345678901234LL;
507   const std::string kBytesSentString("12345678901234");
508
509   stats.set_session(&session_);
510   AddVideoTrackStats();
511   stats.AddStream(stream_);
512
513   // Construct a stats value to read.
514   video_sender_info.add_ssrc(1234);
515   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
523   EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
524   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
525   EXPECT_CALL(*media_channel, GetStats(_, _))
526     .WillOnce(DoAll(SetArgPointee<1>(stats_read),
527                     Return(true)));
528
529   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
530   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.
539 TEST_F(StatsCollectorTest, SessionObjectExists) {
540   webrtc::StatsCollector stats;  // Implementation under test.
541   StatsReports reports;  // returned values.
542   stats.set_session(&session_);
543   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
544   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
545   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
546   stats.GetStats(NULL, &reports);
547   const StatsReport* session_report = FindNthReportByType(
548       reports, StatsReport::kStatsReportTypeSession, 1);
549   EXPECT_FALSE(session_report == NULL);
550 }
551
552 // This test verifies that only one object of type "googSession" exists
553 // in the returned stats.
554 TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) {
555   webrtc::StatsCollector stats;  // Implementation under test.
556   StatsReports reports;  // returned values.
557   stats.set_session(&session_);
558   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
559   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
560   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
561   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
562   stats.GetStats(NULL, &reports);
563   const StatsReport* session_report = FindNthReportByType(
564       reports, StatsReport::kStatsReportTypeSession, 1);
565   EXPECT_FALSE(session_report == NULL);
566   session_report = FindNthReportByType(
567       reports, StatsReport::kStatsReportTypeSession, 2);
568   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.
573 TEST_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);
578   AddVideoTrackStats();
579   stats.AddStream(stream_);
580
581   stats.set_session(&session_);
582
583   StatsReports reports;
584
585   // Verfies the existence of the track report.
586   stats.GetStats(NULL, &reports);
587   EXPECT_EQ((size_t)1, reports.size());
588   EXPECT_EQ(std::string(StatsReport::kStatsReportTypeTrack),
589             reports[0].type);
590
591   std::string trackValue =
592       ExtractStatsValue(StatsReport::kStatsReportTypeTrack,
593                         reports,
594                         StatsReport::kStatsValueNameTrackId);
595   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.
600 TEST_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);
605   AddVideoTrackStats();
606   stats.AddStream(stream_);
607
608   stats.set_session(&session_);
609
610   StatsReports reports;
611
612   // Constructs an ssrc stats update.
613   cricket::VideoSenderInfo video_sender_info;
614   cricket::VideoMediaInfo stats_read;
615   const int64 kBytesSent = 12345678901234LL;
616
617   // Construct a stats value to read.
618   video_sender_info.add_ssrc(1234);
619   video_sender_info.bytes_sent = kBytesSent;
620   stats_read.senders.push_back(video_sender_info);
621
622   EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
623   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
624   EXPECT_CALL(*media_channel, GetStats(_, _))
625     .WillOnce(DoAll(SetArgPointee<1>(stats_read),
626                     Return(true)));
627
628   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
629   stats.GetStats(NULL, &reports);
630   // |reports| should contain at least one session report, one track report,
631   // and one ssrc report.
632   EXPECT_LE((size_t)3, reports.size());
633   const StatsReport* track_report = FindNthReportByType(
634       reports, StatsReport::kStatsReportTypeTrack, 1);
635   EXPECT_FALSE(track_report == NULL);
636
637   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());
641   track_report = FindNthReportByType(
642       reports, StatsReport::kStatsReportTypeTrack, 1);
643   EXPECT_FALSE(track_report == NULL);
644
645   std::string ssrc_id = ExtractSsrcStatsValue(
646       reports, StatsReport::kStatsValueNameSsrc);
647   EXPECT_EQ(talk_base::ToString<uint32>(kSsrcOfTrack), ssrc_id);
648
649   std::string track_id = ExtractSsrcStatsValue(
650       reports, StatsReport::kStatsValueNameTrackId);
651   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.
656 TEST_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);
663   AddVideoTrackStats();
664   stats.AddStream(stream_);
665
666   stats.set_session(&session_);
667
668   StatsReports reports;
669
670   // Constructs an ssrc stats update.
671   cricket::VideoSenderInfo video_sender_info;
672   cricket::VideoMediaInfo stats_read;
673   const int64 kBytesSent = 12345678901234LL;
674
675   // Construct a stats value to read.
676   video_sender_info.add_ssrc(1234);
677   video_sender_info.bytes_sent = kBytesSent;
678   stats_read.senders.push_back(video_sender_info);
679
680   EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
681   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
682   EXPECT_CALL(*media_channel, GetStats(_, _))
683     .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
684                           Return(true)));
685
686   InitSessionStats(kVcName);
687   EXPECT_CALL(session_, GetStats(_))
688       .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
689                             Return(true)));
690
691   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
692   stats.GetStats(NULL, &reports);
693   std::string transport_id = ExtractStatsValue(
694       StatsReport::kStatsReportTypeSsrc,
695       reports,
696       StatsReport::kStatsValueNameTransportId);
697   ASSERT_NE(kNotFound, transport_id);
698   const StatsReport* transport_report = FindReportById(reports,
699                                                        transport_id);
700   ASSERT_FALSE(transport_report == NULL);
701 }
702
703 // This test verifies that a remote stats object will not be created for
704 // an outgoing SSRC where remote stats are not returned.
705 TEST_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
717   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
718   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
719
720   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
721   StatsReports reports;
722   stats.GetStats(NULL, &reports);
723   const StatsReport* remote_report = FindNthReportByType(reports,
724       StatsReport::kStatsReportTypeRemoteSsrc, 1);
725   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.
730 TEST_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
742   StatsReports reports;
743
744   // Instruct the session to return stats containing the transport channel.
745   InitSessionStats(kVcName);
746   EXPECT_CALL(session_, GetStats(_))
747       .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_),
748                             Return(true)));
749
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;
757   video_sender_info.add_ssrc(kSsrcOfTrack);
758   video_sender_info.remote_stats.push_back(remote_ssrc_stats);
759   stats_read.senders.push_back(video_sender_info);
760
761   EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel));
762   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
763   EXPECT_CALL(*media_channel, GetStats(_, _))
764     .WillRepeatedly(DoAll(SetArgPointee<1>(stats_read),
765                           Return(true)));
766
767   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
768   stats.GetStats(NULL, &reports);
769   const StatsReport* remote_report = FindNthReportByType(reports,
770       StatsReport::kStatsReportTypeRemoteSsrc, 1);
771   EXPECT_FALSE(remote_report == NULL);
772   EXPECT_NE(0, remote_report->timestamp);
773 }
774
775 // This test verifies that all chained certificates are correctly
776 // reported
777 TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) {
778   // 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.
800 TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) {
801   // 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.
815 TEST_F(StatsCollectorTest, NoTransport) {
816   webrtc::StatsCollector stats;  // Implementation under test.
817   StatsReports reports;  // returned values.
818   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)));
838
839   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
840   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
841
842   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
843   stats.GetStats(NULL, &reports);
844
845   // Check that the local certificate is absent.
846   std::string local_certificate_id = ExtractStatsValue(
847       StatsReport::kStatsReportTypeComponent,
848       reports,
849       StatsReport::kStatsValueNameLocalCertificateId);
850   ASSERT_EQ(kNotFound, local_certificate_id);
851
852   // Check that the remote certificate is absent.
853   std::string remote_certificate_id = ExtractStatsValue(
854       StatsReport::kStatsReportTypeComponent,
855       reports,
856       StatsReport::kStatsValueNameRemoteCertificateId);
857   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.
862 TEST_F(StatsCollectorTest, NoCertificates) {
863   webrtc::StatsCollector stats;  // Implementation under test.
864   StatsReports reports;  // returned values.
865   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)));
892   EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
893   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
894
895   stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard);
896   stats.GetStats(NULL, &reports);
897
898   // Check that the local certificate is absent.
899   std::string local_certificate_id = ExtractStatsValue(
900       StatsReport::kStatsReportTypeComponent,
901       reports,
902       StatsReport::kStatsValueNameLocalCertificateId);
903   ASSERT_EQ(kNotFound, local_certificate_id);
904
905   // Check that the remote certificate is absent.
906   std::string remote_certificate_id = ExtractStatsValue(
907       StatsReport::kStatsReportTypeComponent,
908       reports,
909       StatsReport::kStatsValueNameRemoteCertificateId);
910   ASSERT_EQ(kNotFound, remote_certificate_id);
911 }
912
913 // This test verifies that a remote certificate with an unsupported digest
914 // algorithm is correctly ignored.
915 TEST_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.
931 TEST_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
938   StatsReports reports;  // returned values.
939   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));
950   EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
951
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
973 // This test verifies that a local stats object can get statistics via
974 // AudioTrackInterface::GetStats() method.
975 TEST_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.
1072 TEST_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
1144 }  // namespace