OLD | NEW |
| (Empty) |
1 /* | |
2 * libjingle | |
3 * Copyright 2014 Google Inc. | |
4 * | |
5 * Redistribution and use in source and binary forms, with or without | |
6 * modification, are permitted provided that the following conditions are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright notice, | |
9 * this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 * this list of conditions and the following disclaimer in the documentation | |
12 * and/or other materials provided with the distribution. | |
13 * 3. The name of the author may not be used to endorse or promote products | |
14 * derived from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 */ | |
27 | |
28 #include <stdio.h> | |
29 | |
30 #include <algorithm> | |
31 | |
32 #include "talk/app/webrtc/statscollector.h" | |
33 | |
34 #include "talk/app/webrtc/peerconnection.h" | |
35 #include "talk/app/webrtc/peerconnectionfactory.h" | |
36 #include "talk/app/webrtc/mediastream.h" | |
37 #include "talk/app/webrtc/mediastreaminterface.h" | |
38 #include "talk/app/webrtc/mediastreamtrack.h" | |
39 #include "talk/app/webrtc/test/fakedatachannelprovider.h" | |
40 #include "talk/app/webrtc/videotrack.h" | |
41 #include "talk/media/base/fakemediaengine.h" | |
42 #include "talk/session/media/channelmanager.h" | |
43 #include "testing/gmock/include/gmock/gmock.h" | |
44 #include "testing/gtest/include/gtest/gtest.h" | |
45 #include "webrtc/base/base64.h" | |
46 #include "webrtc/base/fakesslidentity.h" | |
47 #include "webrtc/base/gunit.h" | |
48 #include "webrtc/base/network.h" | |
49 #include "webrtc/p2p/base/faketransportcontroller.h" | |
50 | |
51 using rtc::scoped_ptr; | |
52 using testing::_; | |
53 using testing::DoAll; | |
54 using testing::Field; | |
55 using testing::Return; | |
56 using testing::ReturnNull; | |
57 using testing::ReturnRef; | |
58 using testing::SetArgPointee; | |
59 using webrtc::PeerConnectionInterface; | |
60 using webrtc::StatsReport; | |
61 using webrtc::StatsReports; | |
62 | |
63 namespace { | |
64 // This value comes from openssl/tls1.h | |
65 const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014; | |
66 } // namespace | |
67 | |
68 namespace cricket { | |
69 | |
70 class ChannelManager; | |
71 | |
72 } // namespace cricket | |
73 | |
74 namespace webrtc { | |
75 | |
76 // Error return values | |
77 const char kNotFound[] = "NOT FOUND"; | |
78 | |
79 // Constant names for track identification. | |
80 const char kLocalTrackId[] = "local_track_id"; | |
81 const char kRemoteTrackId[] = "remote_track_id"; | |
82 const uint32_t kSsrcOfTrack = 1234; | |
83 | |
84 class MockWebRtcSession : public webrtc::WebRtcSession { | |
85 public: | |
86 explicit MockWebRtcSession(webrtc::MediaControllerInterface* media_controller) | |
87 : WebRtcSession(media_controller, | |
88 rtc::Thread::Current(), | |
89 rtc::Thread::Current(), | |
90 nullptr) {} | |
91 MOCK_METHOD0(voice_channel, cricket::VoiceChannel*()); | |
92 MOCK_METHOD0(video_channel, cricket::VideoChannel*()); | |
93 // Libjingle uses "local" for a outgoing track, and "remote" for a incoming | |
94 // track. | |
95 MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*)); | |
96 MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*)); | |
97 MOCK_METHOD1(GetTransportStats, bool(SessionStats*)); | |
98 MOCK_METHOD2(GetLocalCertificate, | |
99 bool(const std::string& transport_name, | |
100 rtc::scoped_refptr<rtc::RTCCertificate>* certificate)); | |
101 MOCK_METHOD2(GetRemoteSSLCertificate, | |
102 bool(const std::string& transport_name, | |
103 rtc::SSLCertificate** cert)); | |
104 }; | |
105 | |
106 // The factory isn't really used; it just satisfies the base PeerConnection. | |
107 class FakePeerConnectionFactory | |
108 : public rtc::RefCountedObject<PeerConnectionFactory> {}; | |
109 | |
110 class MockPeerConnection | |
111 : public rtc::RefCountedObject<webrtc::PeerConnection> { | |
112 public: | |
113 MockPeerConnection() | |
114 : rtc::RefCountedObject<webrtc::PeerConnection>( | |
115 new FakePeerConnectionFactory()) {} | |
116 MOCK_METHOD0(session, WebRtcSession*()); | |
117 MOCK_CONST_METHOD0(sctp_data_channels, | |
118 const std::vector<rtc::scoped_refptr<DataChannel>>&()); | |
119 }; | |
120 | |
121 class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel { | |
122 public: | |
123 MockVideoMediaChannel() : | |
124 cricket::FakeVideoMediaChannel(NULL, cricket::VideoOptions()) {} | |
125 MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*)); | |
126 }; | |
127 | |
128 class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel { | |
129 public: | |
130 MockVoiceMediaChannel() : | |
131 cricket::FakeVoiceMediaChannel(NULL, cricket::AudioOptions()) {} | |
132 MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*)); | |
133 }; | |
134 | |
135 class FakeAudioProcessor : public webrtc::AudioProcessorInterface { | |
136 public: | |
137 FakeAudioProcessor() {} | |
138 ~FakeAudioProcessor() {} | |
139 | |
140 private: | |
141 void GetStats(AudioProcessorInterface::AudioProcessorStats* stats) override { | |
142 stats->typing_noise_detected = true; | |
143 stats->echo_return_loss = 2; | |
144 stats->echo_return_loss_enhancement = 3; | |
145 stats->echo_delay_median_ms = 4; | |
146 stats->aec_quality_min = 5.1f; | |
147 stats->echo_delay_std_ms = 6; | |
148 } | |
149 }; | |
150 | |
151 class FakeAudioTrack | |
152 : public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface> { | |
153 public: | |
154 explicit FakeAudioTrack(const std::string& id) | |
155 : webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(id), | |
156 processor_(new rtc::RefCountedObject<FakeAudioProcessor>()) {} | |
157 std::string kind() const override { return "audio"; } | |
158 webrtc::AudioSourceInterface* GetSource() const override { return NULL; } | |
159 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} | |
160 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} | |
161 bool GetSignalLevel(int* level) override { | |
162 *level = 1; | |
163 return true; | |
164 } | |
165 rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor() | |
166 override { | |
167 return processor_; | |
168 } | |
169 | |
170 private: | |
171 rtc::scoped_refptr<FakeAudioProcessor> processor_; | |
172 }; | |
173 | |
174 bool GetValue(const StatsReport* report, | |
175 StatsReport::StatsValueName name, | |
176 std::string* value) { | |
177 const StatsReport::Value* v = report->FindValue(name); | |
178 if (!v) | |
179 return false; | |
180 *value = v->ToString(); | |
181 return true; | |
182 } | |
183 | |
184 std::string ExtractStatsValue(const StatsReport::StatsType& type, | |
185 const StatsReports& reports, | |
186 StatsReport::StatsValueName name) { | |
187 for (const auto* r : reports) { | |
188 std::string ret; | |
189 if (r->type() == type && GetValue(r, name, &ret)) | |
190 return ret; | |
191 } | |
192 | |
193 return kNotFound; | |
194 } | |
195 | |
196 StatsReport::Id TypedIdFromIdString(StatsReport::StatsType type, | |
197 const std::string& value) { | |
198 EXPECT_FALSE(value.empty()); | |
199 StatsReport::Id id; | |
200 if (value.empty()) | |
201 return id; | |
202 | |
203 // This has assumptions about how the ID is constructed. As is, this is | |
204 // OK since this is for testing purposes only, but if we ever need this | |
205 // in production, we should add a generic method that does this. | |
206 size_t index = value.find('_'); | |
207 EXPECT_NE(index, std::string::npos); | |
208 if (index == std::string::npos || index == (value.length() - 1)) | |
209 return id; | |
210 | |
211 id = StatsReport::NewTypedId(type, value.substr(index + 1)); | |
212 EXPECT_EQ(id->ToString(), value); | |
213 return id; | |
214 } | |
215 | |
216 StatsReport::Id IdFromCertIdString(const std::string& cert_id) { | |
217 return TypedIdFromIdString(StatsReport::kStatsReportTypeCertificate, cert_id); | |
218 } | |
219 | |
220 // Finds the |n|-th report of type |type| in |reports|. | |
221 // |n| starts from 1 for finding the first report. | |
222 const StatsReport* FindNthReportByType( | |
223 const StatsReports& reports, const StatsReport::StatsType& type, int n) { | |
224 for (size_t i = 0; i < reports.size(); ++i) { | |
225 if (reports[i]->type() == type) { | |
226 n--; | |
227 if (n == 0) | |
228 return reports[i]; | |
229 } | |
230 } | |
231 return nullptr; | |
232 } | |
233 | |
234 const StatsReport* FindReportById(const StatsReports& reports, | |
235 const StatsReport::Id& id) { | |
236 for (const auto* r : reports) { | |
237 if (r->id()->Equals(id)) | |
238 return r; | |
239 } | |
240 return nullptr; | |
241 } | |
242 | |
243 std::string ExtractSsrcStatsValue(StatsReports reports, | |
244 StatsReport::StatsValueName name) { | |
245 return ExtractStatsValue(StatsReport::kStatsReportTypeSsrc, reports, name); | |
246 } | |
247 | |
248 std::string ExtractBweStatsValue(StatsReports reports, | |
249 StatsReport::StatsValueName name) { | |
250 return ExtractStatsValue( | |
251 StatsReport::kStatsReportTypeBwe, reports, name); | |
252 } | |
253 | |
254 std::string DerToPem(const std::string& der) { | |
255 return rtc::SSLIdentity::DerToPem( | |
256 rtc::kPemTypeCertificate, | |
257 reinterpret_cast<const unsigned char*>(der.c_str()), | |
258 der.length()); | |
259 } | |
260 | |
261 std::vector<std::string> DersToPems( | |
262 const std::vector<std::string>& ders) { | |
263 std::vector<std::string> pems(ders.size()); | |
264 std::transform(ders.begin(), ders.end(), pems.begin(), DerToPem); | |
265 return pems; | |
266 } | |
267 | |
268 void CheckCertChainReports(const StatsReports& reports, | |
269 const std::vector<std::string>& ders, | |
270 const StatsReport::Id& start_id) { | |
271 StatsReport::Id cert_id; | |
272 const StatsReport::Id* certificate_id = &start_id; | |
273 size_t i = 0; | |
274 while (true) { | |
275 const StatsReport* report = FindReportById(reports, *certificate_id); | |
276 ASSERT_TRUE(report != NULL); | |
277 | |
278 std::string der_base64; | |
279 EXPECT_TRUE(GetValue( | |
280 report, StatsReport::kStatsValueNameDer, &der_base64)); | |
281 std::string der = rtc::Base64::Decode(der_base64, rtc::Base64::DO_STRICT); | |
282 EXPECT_EQ(ders[i], der); | |
283 | |
284 std::string fingerprint_algorithm; | |
285 EXPECT_TRUE(GetValue( | |
286 report, | |
287 StatsReport::kStatsValueNameFingerprintAlgorithm, | |
288 &fingerprint_algorithm)); | |
289 // The digest algorithm for a FakeSSLCertificate is always SHA-1. | |
290 std::string sha_1_str = rtc::DIGEST_SHA_1; | |
291 EXPECT_EQ(sha_1_str, fingerprint_algorithm); | |
292 | |
293 std::string fingerprint; | |
294 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameFingerprint, | |
295 &fingerprint)); | |
296 EXPECT_FALSE(fingerprint.empty()); | |
297 | |
298 ++i; | |
299 std::string issuer_id; | |
300 if (!GetValue(report, StatsReport::kStatsValueNameIssuerId, | |
301 &issuer_id)) { | |
302 break; | |
303 } | |
304 | |
305 cert_id = IdFromCertIdString(issuer_id); | |
306 certificate_id = &cert_id; | |
307 } | |
308 EXPECT_EQ(ders.size(), i); | |
309 } | |
310 | |
311 void VerifyVoiceReceiverInfoReport( | |
312 const StatsReport* report, | |
313 const cricket::VoiceReceiverInfo& info) { | |
314 std::string value_in_report; | |
315 EXPECT_TRUE(GetValue( | |
316 report, StatsReport::kStatsValueNameAudioOutputLevel, &value_in_report)); | |
317 EXPECT_EQ(rtc::ToString<int>(info.audio_level), value_in_report); | |
318 EXPECT_TRUE(GetValue( | |
319 report, StatsReport::kStatsValueNameBytesReceived, &value_in_report)); | |
320 EXPECT_EQ(rtc::ToString<int64_t>(info.bytes_rcvd), value_in_report); | |
321 EXPECT_TRUE(GetValue( | |
322 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); | |
323 EXPECT_EQ(rtc::ToString<int>(info.jitter_ms), value_in_report); | |
324 EXPECT_TRUE(GetValue( | |
325 report, StatsReport::kStatsValueNameJitterBufferMs, &value_in_report)); | |
326 EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_ms), value_in_report); | |
327 EXPECT_TRUE(GetValue( | |
328 report, StatsReport::kStatsValueNamePreferredJitterBufferMs, | |
329 &value_in_report)); | |
330 EXPECT_EQ(rtc::ToString<int>(info.jitter_buffer_preferred_ms), | |
331 value_in_report); | |
332 EXPECT_TRUE(GetValue( | |
333 report, StatsReport::kStatsValueNameCurrentDelayMs, &value_in_report)); | |
334 EXPECT_EQ(rtc::ToString<int>(info.delay_estimate_ms), value_in_report); | |
335 EXPECT_TRUE(GetValue( | |
336 report, StatsReport::kStatsValueNameExpandRate, &value_in_report)); | |
337 EXPECT_EQ(rtc::ToString<float>(info.expand_rate), value_in_report); | |
338 EXPECT_TRUE(GetValue( | |
339 report, StatsReport::kStatsValueNameSpeechExpandRate, &value_in_report)); | |
340 EXPECT_EQ(rtc::ToString<float>(info.speech_expand_rate), value_in_report); | |
341 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameAccelerateRate, | |
342 &value_in_report)); | |
343 EXPECT_EQ(rtc::ToString<float>(info.accelerate_rate), value_in_report); | |
344 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNamePreemptiveExpandRate, | |
345 &value_in_report)); | |
346 EXPECT_EQ(rtc::ToString<float>(info.preemptive_expand_rate), value_in_report); | |
347 EXPECT_TRUE(GetValue(report, StatsReport::kStatsValueNameSecondaryDecodedRate, | |
348 &value_in_report)); | |
349 EXPECT_EQ(rtc::ToString<float>(info.secondary_decoded_rate), value_in_report); | |
350 EXPECT_TRUE(GetValue( | |
351 report, StatsReport::kStatsValueNamePacketsReceived, &value_in_report)); | |
352 EXPECT_EQ(rtc::ToString<int>(info.packets_rcvd), value_in_report); | |
353 EXPECT_TRUE(GetValue( | |
354 report, StatsReport::kStatsValueNameDecodingCTSG, &value_in_report)); | |
355 EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_silence_generator), | |
356 value_in_report); | |
357 EXPECT_TRUE(GetValue( | |
358 report, StatsReport::kStatsValueNameDecodingCTN, &value_in_report)); | |
359 EXPECT_EQ(rtc::ToString<int>(info.decoding_calls_to_neteq), | |
360 value_in_report); | |
361 EXPECT_TRUE(GetValue( | |
362 report, StatsReport::kStatsValueNameDecodingNormal, &value_in_report)); | |
363 EXPECT_EQ(rtc::ToString<int>(info.decoding_normal), value_in_report); | |
364 EXPECT_TRUE(GetValue( | |
365 report, StatsReport::kStatsValueNameDecodingPLC, &value_in_report)); | |
366 EXPECT_EQ(rtc::ToString<int>(info.decoding_plc), value_in_report); | |
367 EXPECT_TRUE(GetValue( | |
368 report, StatsReport::kStatsValueNameDecodingCNG, &value_in_report)); | |
369 EXPECT_EQ(rtc::ToString<int>(info.decoding_cng), value_in_report); | |
370 EXPECT_TRUE(GetValue( | |
371 report, StatsReport::kStatsValueNameDecodingPLCCNG, &value_in_report)); | |
372 EXPECT_EQ(rtc::ToString<int>(info.decoding_plc_cng), value_in_report); | |
373 EXPECT_TRUE(GetValue( | |
374 report, StatsReport::kStatsValueNameCodecName, &value_in_report)); | |
375 } | |
376 | |
377 | |
378 void VerifyVoiceSenderInfoReport(const StatsReport* report, | |
379 const cricket::VoiceSenderInfo& sinfo) { | |
380 std::string value_in_report; | |
381 EXPECT_TRUE(GetValue( | |
382 report, StatsReport::kStatsValueNameCodecName, &value_in_report)); | |
383 EXPECT_EQ(sinfo.codec_name, value_in_report); | |
384 EXPECT_TRUE(GetValue( | |
385 report, StatsReport::kStatsValueNameBytesSent, &value_in_report)); | |
386 EXPECT_EQ(rtc::ToString<int64_t>(sinfo.bytes_sent), value_in_report); | |
387 EXPECT_TRUE(GetValue( | |
388 report, StatsReport::kStatsValueNamePacketsSent, &value_in_report)); | |
389 EXPECT_EQ(rtc::ToString<int>(sinfo.packets_sent), value_in_report); | |
390 EXPECT_TRUE(GetValue( | |
391 report, StatsReport::kStatsValueNamePacketsLost, &value_in_report)); | |
392 EXPECT_EQ(rtc::ToString<int>(sinfo.packets_lost), value_in_report); | |
393 EXPECT_TRUE(GetValue( | |
394 report, StatsReport::kStatsValueNameRtt, &value_in_report)); | |
395 EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report); | |
396 EXPECT_TRUE(GetValue( | |
397 report, StatsReport::kStatsValueNameRtt, &value_in_report)); | |
398 EXPECT_EQ(rtc::ToString<int>(sinfo.rtt_ms), value_in_report); | |
399 EXPECT_TRUE(GetValue( | |
400 report, StatsReport::kStatsValueNameJitterReceived, &value_in_report)); | |
401 EXPECT_EQ(rtc::ToString<int>(sinfo.jitter_ms), value_in_report); | |
402 EXPECT_TRUE(GetValue( | |
403 report, StatsReport::kStatsValueNameEchoCancellationQualityMin, | |
404 &value_in_report)); | |
405 EXPECT_EQ(rtc::ToString<float>(sinfo.aec_quality_min), value_in_report); | |
406 EXPECT_TRUE(GetValue( | |
407 report, StatsReport::kStatsValueNameEchoDelayMedian, &value_in_report)); | |
408 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_delay_median_ms), | |
409 value_in_report); | |
410 EXPECT_TRUE(GetValue( | |
411 report, StatsReport::kStatsValueNameEchoDelayStdDev, &value_in_report)); | |
412 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_delay_std_ms), | |
413 value_in_report); | |
414 EXPECT_TRUE(GetValue( | |
415 report, StatsReport::kStatsValueNameEchoReturnLoss, &value_in_report)); | |
416 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_return_loss), | |
417 value_in_report); | |
418 EXPECT_TRUE(GetValue( | |
419 report, StatsReport::kStatsValueNameEchoReturnLossEnhancement, | |
420 &value_in_report)); | |
421 EXPECT_EQ(rtc::ToString<int>(sinfo.echo_return_loss_enhancement), | |
422 value_in_report); | |
423 EXPECT_TRUE(GetValue( | |
424 report, StatsReport::kStatsValueNameAudioInputLevel, &value_in_report)); | |
425 EXPECT_EQ(rtc::ToString<int>(sinfo.audio_level), value_in_report); | |
426 EXPECT_TRUE(GetValue( | |
427 report, StatsReport::kStatsValueNameTypingNoiseState, &value_in_report)); | |
428 std::string typing_detected = sinfo.typing_noise_detected ? "true" : "false"; | |
429 EXPECT_EQ(typing_detected, value_in_report); | |
430 } | |
431 | |
432 // Helper methods to avoid duplication of code. | |
433 void InitVoiceSenderInfo(cricket::VoiceSenderInfo* voice_sender_info) { | |
434 voice_sender_info->add_ssrc(kSsrcOfTrack); | |
435 voice_sender_info->codec_name = "fake_codec"; | |
436 voice_sender_info->bytes_sent = 100; | |
437 voice_sender_info->packets_sent = 101; | |
438 voice_sender_info->rtt_ms = 102; | |
439 voice_sender_info->fraction_lost = 103; | |
440 voice_sender_info->jitter_ms = 104; | |
441 voice_sender_info->packets_lost = 105; | |
442 voice_sender_info->ext_seqnum = 106; | |
443 voice_sender_info->audio_level = 107; | |
444 voice_sender_info->echo_return_loss = 108; | |
445 voice_sender_info->echo_return_loss_enhancement = 109; | |
446 voice_sender_info->echo_delay_median_ms = 110; | |
447 voice_sender_info->echo_delay_std_ms = 111; | |
448 voice_sender_info->aec_quality_min = 112.0f; | |
449 voice_sender_info->typing_noise_detected = false; | |
450 } | |
451 | |
452 void UpdateVoiceSenderInfoFromAudioTrack( | |
453 FakeAudioTrack* audio_track, cricket::VoiceSenderInfo* voice_sender_info) { | |
454 audio_track->GetSignalLevel(&voice_sender_info->audio_level); | |
455 webrtc::AudioProcessorInterface::AudioProcessorStats audio_processor_stats; | |
456 audio_track->GetAudioProcessor()->GetStats(&audio_processor_stats); | |
457 voice_sender_info->typing_noise_detected = | |
458 audio_processor_stats.typing_noise_detected; | |
459 voice_sender_info->echo_return_loss = audio_processor_stats.echo_return_loss; | |
460 voice_sender_info->echo_return_loss_enhancement = | |
461 audio_processor_stats.echo_return_loss_enhancement; | |
462 voice_sender_info->echo_delay_median_ms = | |
463 audio_processor_stats.echo_delay_median_ms; | |
464 voice_sender_info->aec_quality_min = audio_processor_stats.aec_quality_min; | |
465 voice_sender_info->echo_delay_std_ms = | |
466 audio_processor_stats.echo_delay_std_ms; | |
467 } | |
468 | |
469 void InitVoiceReceiverInfo(cricket::VoiceReceiverInfo* voice_receiver_info) { | |
470 voice_receiver_info->add_ssrc(kSsrcOfTrack); | |
471 voice_receiver_info->bytes_rcvd = 110; | |
472 voice_receiver_info->packets_rcvd = 111; | |
473 voice_receiver_info->packets_lost = 112; | |
474 voice_receiver_info->fraction_lost = 113; | |
475 voice_receiver_info->packets_lost = 114; | |
476 voice_receiver_info->ext_seqnum = 115; | |
477 voice_receiver_info->jitter_ms = 116; | |
478 voice_receiver_info->jitter_buffer_ms = 117; | |
479 voice_receiver_info->jitter_buffer_preferred_ms = 118; | |
480 voice_receiver_info->delay_estimate_ms = 119; | |
481 voice_receiver_info->audio_level = 120; | |
482 voice_receiver_info->expand_rate = 121; | |
483 voice_receiver_info->speech_expand_rate = 122; | |
484 voice_receiver_info->secondary_decoded_rate = 123; | |
485 voice_receiver_info->accelerate_rate = 124; | |
486 voice_receiver_info->preemptive_expand_rate = 125; | |
487 } | |
488 | |
489 class StatsCollectorForTest : public webrtc::StatsCollector { | |
490 public: | |
491 explicit StatsCollectorForTest(PeerConnection* pc) | |
492 : StatsCollector(pc), time_now_(19477) {} | |
493 | |
494 double GetTimeNow() override { | |
495 return time_now_; | |
496 } | |
497 | |
498 private: | |
499 double time_now_; | |
500 }; | |
501 | |
502 class StatsCollectorTest : public testing::Test { | |
503 protected: | |
504 StatsCollectorTest() | |
505 : media_engine_(new cricket::FakeMediaEngine()), | |
506 channel_manager_( | |
507 new cricket::ChannelManager(media_engine_, rtc::Thread::Current())), | |
508 media_controller_( | |
509 webrtc::MediaControllerInterface::Create(rtc::Thread::Current(), | |
510 channel_manager_.get())), | |
511 session_(media_controller_.get()) { | |
512 // By default, we ignore session GetStats calls. | |
513 EXPECT_CALL(session_, GetTransportStats(_)).WillRepeatedly(Return(false)); | |
514 // Add default returns for mock classes. | |
515 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
516 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
517 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_)); | |
518 EXPECT_CALL(pc_, sctp_data_channels()) | |
519 .WillRepeatedly(ReturnRef(data_channels_)); | |
520 } | |
521 | |
522 ~StatsCollectorTest() {} | |
523 | |
524 // This creates a standard setup with a transport called "trspname" | |
525 // having one transport channel | |
526 // and the specified virtual connection name. | |
527 void InitSessionStats(const std::string& vc_name) { | |
528 const std::string kTransportName("trspname"); | |
529 cricket::TransportStats transport_stats; | |
530 cricket::TransportChannelStats channel_stats; | |
531 channel_stats.component = 1; | |
532 transport_stats.transport_name = kTransportName; | |
533 transport_stats.channel_stats.push_back(channel_stats); | |
534 | |
535 session_stats_.transport_stats[kTransportName] = transport_stats; | |
536 session_stats_.proxy_to_transport[vc_name] = kTransportName; | |
537 } | |
538 | |
539 // Adds a outgoing video track with a given SSRC into the stats. | |
540 void AddOutgoingVideoTrackStats() { | |
541 stream_ = webrtc::MediaStream::Create("streamlabel"); | |
542 track_= webrtc::VideoTrack::Create(kLocalTrackId, NULL); | |
543 stream_->AddTrack(track_); | |
544 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) | |
545 .WillRepeatedly(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); | |
546 } | |
547 | |
548 // Adds a incoming video track with a given SSRC into the stats. | |
549 void AddIncomingVideoTrackStats() { | |
550 stream_ = webrtc::MediaStream::Create("streamlabel"); | |
551 track_= webrtc::VideoTrack::Create(kRemoteTrackId, NULL); | |
552 stream_->AddTrack(track_); | |
553 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) | |
554 .WillRepeatedly(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); | |
555 } | |
556 | |
557 // Adds a outgoing audio track with a given SSRC into the stats. | |
558 void AddOutgoingAudioTrackStats() { | |
559 if (stream_ == NULL) | |
560 stream_ = webrtc::MediaStream::Create("streamlabel"); | |
561 | |
562 audio_track_ = new rtc::RefCountedObject<FakeAudioTrack>( | |
563 kLocalTrackId); | |
564 stream_->AddTrack(audio_track_); | |
565 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) | |
566 .WillOnce(DoAll(SetArgPointee<1>(kLocalTrackId), Return(true))); | |
567 } | |
568 | |
569 // Adds a incoming audio track with a given SSRC into the stats. | |
570 void AddIncomingAudioTrackStats() { | |
571 if (stream_ == NULL) | |
572 stream_ = webrtc::MediaStream::Create("streamlabel"); | |
573 | |
574 audio_track_ = new rtc::RefCountedObject<FakeAudioTrack>( | |
575 kRemoteTrackId); | |
576 stream_->AddTrack(audio_track_); | |
577 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) | |
578 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); | |
579 } | |
580 | |
581 void AddDataChannel(cricket::DataChannelType type, | |
582 const std::string& label, | |
583 int id) { | |
584 InternalDataChannelInit config; | |
585 config.id = id; | |
586 | |
587 data_channels_.push_back(DataChannel::Create( | |
588 &data_channel_provider_, cricket::DCT_SCTP, label, config)); | |
589 } | |
590 | |
591 StatsReport* AddCandidateReport(StatsCollector* collector, | |
592 const cricket::Candidate& candidate, | |
593 bool local) { | |
594 return collector->AddCandidateReport(candidate, local); | |
595 } | |
596 | |
597 void SetupAndVerifyAudioTrackStats( | |
598 FakeAudioTrack* audio_track, | |
599 webrtc::MediaStream* stream, | |
600 webrtc::StatsCollector* stats, | |
601 cricket::VoiceChannel* voice_channel, | |
602 const std::string& vc_name, | |
603 MockVoiceMediaChannel* media_channel, | |
604 cricket::VoiceSenderInfo* voice_sender_info, | |
605 cricket::VoiceReceiverInfo* voice_receiver_info, | |
606 cricket::VoiceMediaInfo* stats_read, | |
607 StatsReports* reports) { | |
608 // A track can't have both sender report and recv report at the same time | |
609 // for now, this might change in the future though. | |
610 ASSERT((voice_sender_info == NULL) ^ (voice_receiver_info == NULL)); | |
611 | |
612 // Instruct the session to return stats containing the transport channel. | |
613 InitSessionStats(vc_name); | |
614 EXPECT_CALL(session_, GetTransportStats(_)) | |
615 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
616 Return(true))); | |
617 | |
618 // Constructs an ssrc stats update. | |
619 if (voice_sender_info) | |
620 stats_read->senders.push_back(*voice_sender_info); | |
621 if (voice_receiver_info) | |
622 stats_read->receivers.push_back(*voice_receiver_info); | |
623 | |
624 EXPECT_CALL(session_, voice_channel()).WillRepeatedly( | |
625 Return(voice_channel)); | |
626 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
627 EXPECT_CALL(*media_channel, GetStats(_)) | |
628 .WillOnce(DoAll(SetArgPointee<0>(*stats_read), Return(true))); | |
629 | |
630 stats->UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
631 stats->ClearUpdateStatsCacheForTest(); | |
632 stats->GetStats(NULL, reports); | |
633 | |
634 // Verify the existence of the track report. | |
635 const StatsReport* report = FindNthReportByType( | |
636 *reports, StatsReport::kStatsReportTypeSsrc, 1); | |
637 EXPECT_FALSE(report == NULL); | |
638 EXPECT_EQ(stats->GetTimeNow(), report->timestamp()); | |
639 std::string track_id = ExtractSsrcStatsValue( | |
640 *reports, StatsReport::kStatsValueNameTrackId); | |
641 EXPECT_EQ(audio_track->id(), track_id); | |
642 std::string ssrc_id = ExtractSsrcStatsValue( | |
643 *reports, StatsReport::kStatsValueNameSsrc); | |
644 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
645 | |
646 // Verifies the values in the track report. | |
647 if (voice_sender_info) { | |
648 UpdateVoiceSenderInfoFromAudioTrack(audio_track, voice_sender_info); | |
649 VerifyVoiceSenderInfoReport(report, *voice_sender_info); | |
650 } | |
651 if (voice_receiver_info) { | |
652 VerifyVoiceReceiverInfoReport(report, *voice_receiver_info); | |
653 } | |
654 | |
655 // Verify we get the same result by passing a track to GetStats(). | |
656 StatsReports track_reports; // returned values. | |
657 stats->GetStats(audio_track, &track_reports); | |
658 const StatsReport* track_report = FindNthReportByType( | |
659 track_reports, StatsReport::kStatsReportTypeSsrc, 1); | |
660 EXPECT_TRUE(track_report); | |
661 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); | |
662 track_id = ExtractSsrcStatsValue(track_reports, | |
663 StatsReport::kStatsValueNameTrackId); | |
664 EXPECT_EQ(audio_track->id(), track_id); | |
665 ssrc_id = ExtractSsrcStatsValue(track_reports, | |
666 StatsReport::kStatsValueNameSsrc); | |
667 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
668 if (voice_sender_info) | |
669 VerifyVoiceSenderInfoReport(track_report, *voice_sender_info); | |
670 if (voice_receiver_info) | |
671 VerifyVoiceReceiverInfoReport(track_report, *voice_receiver_info); | |
672 } | |
673 | |
674 void TestCertificateReports(const rtc::FakeSSLCertificate& local_cert, | |
675 const std::vector<std::string>& local_ders, | |
676 const rtc::FakeSSLCertificate& remote_cert, | |
677 const std::vector<std::string>& remote_ders) { | |
678 StatsCollectorForTest stats(&pc_); | |
679 | |
680 StatsReports reports; // returned values. | |
681 | |
682 // Fake stats to process. | |
683 cricket::TransportChannelStats channel_stats; | |
684 channel_stats.component = 1; | |
685 channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; | |
686 channel_stats.ssl_cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; | |
687 | |
688 cricket::TransportStats transport_stats; | |
689 transport_stats.transport_name = "audio"; | |
690 transport_stats.channel_stats.push_back(channel_stats); | |
691 | |
692 SessionStats session_stats; | |
693 session_stats.transport_stats[transport_stats.transport_name] = | |
694 transport_stats; | |
695 | |
696 // Fake certificate to report | |
697 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate( | |
698 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::FakeSSLIdentity>( | |
699 new rtc::FakeSSLIdentity(local_cert)))); | |
700 | |
701 // Configure MockWebRtcSession | |
702 EXPECT_CALL(session_, | |
703 GetLocalCertificate(transport_stats.transport_name, _)) | |
704 .WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true))); | |
705 EXPECT_CALL(session_, | |
706 GetRemoteSSLCertificate(transport_stats.transport_name, _)) | |
707 .WillOnce( | |
708 DoAll(SetArgPointee<1>(remote_cert.GetReference()), Return(true))); | |
709 EXPECT_CALL(session_, GetTransportStats(_)) | |
710 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
711 Return(true))); | |
712 | |
713 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
714 | |
715 stats.GetStats(NULL, &reports); | |
716 | |
717 const StatsReport* channel_report = FindNthReportByType( | |
718 reports, StatsReport::kStatsReportTypeComponent, 1); | |
719 EXPECT_TRUE(channel_report != NULL); | |
720 | |
721 // Check local certificate chain. | |
722 std::string local_certificate_id = ExtractStatsValue( | |
723 StatsReport::kStatsReportTypeComponent, | |
724 reports, | |
725 StatsReport::kStatsValueNameLocalCertificateId); | |
726 if (local_ders.size() > 0) { | |
727 EXPECT_NE(kNotFound, local_certificate_id); | |
728 StatsReport::Id id(IdFromCertIdString(local_certificate_id)); | |
729 CheckCertChainReports(reports, local_ders, id); | |
730 } else { | |
731 EXPECT_EQ(kNotFound, local_certificate_id); | |
732 } | |
733 | |
734 // Check remote certificate chain. | |
735 std::string remote_certificate_id = ExtractStatsValue( | |
736 StatsReport::kStatsReportTypeComponent, | |
737 reports, | |
738 StatsReport::kStatsValueNameRemoteCertificateId); | |
739 if (remote_ders.size() > 0) { | |
740 EXPECT_NE(kNotFound, remote_certificate_id); | |
741 StatsReport::Id id(IdFromCertIdString(remote_certificate_id)); | |
742 CheckCertChainReports(reports, remote_ders, id); | |
743 } else { | |
744 EXPECT_EQ(kNotFound, remote_certificate_id); | |
745 } | |
746 | |
747 // Check negotiated ciphers. | |
748 std::string dtls_cipher_suite = | |
749 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
750 StatsReport::kStatsValueNameDtlsCipher); | |
751 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName( | |
752 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), | |
753 dtls_cipher_suite); | |
754 std::string srtp_crypto_suite = | |
755 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
756 StatsReport::kStatsValueNameSrtpCipher); | |
757 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::SRTP_AES128_CM_SHA1_80), | |
758 srtp_crypto_suite); | |
759 } | |
760 | |
761 cricket::FakeMediaEngine* media_engine_; | |
762 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; | |
763 rtc::scoped_ptr<webrtc::MediaControllerInterface> media_controller_; | |
764 MockWebRtcSession session_; | |
765 MockPeerConnection pc_; | |
766 FakeDataChannelProvider data_channel_provider_; | |
767 SessionStats session_stats_; | |
768 rtc::scoped_refptr<webrtc::MediaStream> stream_; | |
769 rtc::scoped_refptr<webrtc::VideoTrack> track_; | |
770 rtc::scoped_refptr<FakeAudioTrack> audio_track_; | |
771 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; | |
772 }; | |
773 | |
774 // Verify that ExtractDataInfo populates reports. | |
775 TEST_F(StatsCollectorTest, ExtractDataInfo) { | |
776 const std::string label = "hacks"; | |
777 const int id = 31337; | |
778 const std::string state = DataChannelInterface::DataStateString( | |
779 DataChannelInterface::DataState::kConnecting); | |
780 | |
781 AddDataChannel(cricket::DCT_SCTP, label, id); | |
782 StatsCollectorForTest stats(&pc_); | |
783 | |
784 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
785 | |
786 StatsReports reports; | |
787 stats.GetStats(NULL, &reports); | |
788 | |
789 const StatsReport* report = | |
790 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); | |
791 | |
792 StatsReport::Id reportId = StatsReport::NewTypedIntId( | |
793 StatsReport::kStatsReportTypeDataChannel, id); | |
794 | |
795 EXPECT_TRUE(reportId->Equals(report->id())); | |
796 | |
797 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
798 EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
799 reports, | |
800 StatsReport::kStatsValueNameLabel)); | |
801 EXPECT_EQ(rtc::ToString<int64_t>(id), | |
802 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, | |
803 StatsReport::kStatsValueNameDataChannelId)); | |
804 EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
805 reports, | |
806 StatsReport::kStatsValueNameState)); | |
807 EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
808 reports, | |
809 StatsReport::kStatsValueNameProtocol)); | |
810 } | |
811 | |
812 // This test verifies that 64-bit counters are passed successfully. | |
813 TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { | |
814 StatsCollectorForTest stats(&pc_); | |
815 | |
816 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
817 .WillRepeatedly(Return(false)); | |
818 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
819 .WillRepeatedly(Return(false)); | |
820 | |
821 const char kVideoChannelName[] = "video"; | |
822 | |
823 InitSessionStats(kVideoChannelName); | |
824 EXPECT_CALL(session_, GetTransportStats(_)) | |
825 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
826 Return(true))); | |
827 | |
828 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
829 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
830 nullptr, kVideoChannelName, false); | |
831 StatsReports reports; // returned values. | |
832 cricket::VideoSenderInfo video_sender_info; | |
833 cricket::VideoMediaInfo stats_read; | |
834 // The number of bytes must be larger than 0xFFFFFFFF for this test. | |
835 const int64_t kBytesSent = 12345678901234LL; | |
836 const std::string kBytesSentString("12345678901234"); | |
837 | |
838 AddOutgoingVideoTrackStats(); | |
839 stats.AddStream(stream_); | |
840 | |
841 // Construct a stats value to read. | |
842 video_sender_info.add_ssrc(1234); | |
843 video_sender_info.bytes_sent = kBytesSent; | |
844 stats_read.senders.push_back(video_sender_info); | |
845 | |
846 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
847 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
848 EXPECT_CALL(*media_channel, GetStats(_)) | |
849 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
850 Return(true))); | |
851 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
852 stats.GetStats(NULL, &reports); | |
853 std::string result = ExtractSsrcStatsValue(reports, | |
854 StatsReport::kStatsValueNameBytesSent); | |
855 EXPECT_EQ(kBytesSentString, result); | |
856 } | |
857 | |
858 // Test that BWE information is reported via stats. | |
859 TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { | |
860 StatsCollectorForTest stats(&pc_); | |
861 | |
862 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
863 .WillRepeatedly(Return(false)); | |
864 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
865 .WillRepeatedly(Return(false)); | |
866 | |
867 const char kVideoChannelName[] = "video"; | |
868 | |
869 InitSessionStats(kVideoChannelName); | |
870 EXPECT_CALL(session_, GetTransportStats(_)) | |
871 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
872 Return(true))); | |
873 | |
874 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
875 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
876 nullptr, kVideoChannelName, false); | |
877 | |
878 StatsReports reports; // returned values. | |
879 cricket::VideoSenderInfo video_sender_info; | |
880 cricket::VideoMediaInfo stats_read; | |
881 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and | |
882 // BWE. | |
883 const int64_t kBytesSent = 12345678901234LL; | |
884 const std::string kBytesSentString("12345678901234"); | |
885 | |
886 AddOutgoingVideoTrackStats(); | |
887 stats.AddStream(stream_); | |
888 | |
889 // Construct a stats value to read. | |
890 video_sender_info.add_ssrc(1234); | |
891 video_sender_info.bytes_sent = kBytesSent; | |
892 stats_read.senders.push_back(video_sender_info); | |
893 cricket::BandwidthEstimationInfo bwe; | |
894 const int kTargetEncBitrate = 123456; | |
895 const std::string kTargetEncBitrateString("123456"); | |
896 bwe.target_enc_bitrate = kTargetEncBitrate; | |
897 stats_read.bw_estimations.push_back(bwe); | |
898 | |
899 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
900 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
901 EXPECT_CALL(*media_channel, GetStats(_)) | |
902 .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); | |
903 | |
904 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
905 stats.GetStats(NULL, &reports); | |
906 std::string result = ExtractSsrcStatsValue(reports, | |
907 StatsReport::kStatsValueNameBytesSent); | |
908 EXPECT_EQ(kBytesSentString, result); | |
909 result = ExtractBweStatsValue(reports, | |
910 StatsReport::kStatsValueNameTargetEncBitrate); | |
911 EXPECT_EQ(kTargetEncBitrateString, result); | |
912 } | |
913 | |
914 // This test verifies that an object of type "googSession" always | |
915 // exists in the returned stats. | |
916 TEST_F(StatsCollectorTest, SessionObjectExists) { | |
917 StatsCollectorForTest stats(&pc_); | |
918 | |
919 StatsReports reports; // returned values. | |
920 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
921 stats.GetStats(NULL, &reports); | |
922 const StatsReport* session_report = FindNthReportByType( | |
923 reports, StatsReport::kStatsReportTypeSession, 1); | |
924 EXPECT_FALSE(session_report == NULL); | |
925 } | |
926 | |
927 // This test verifies that only one object of type "googSession" exists | |
928 // in the returned stats. | |
929 TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { | |
930 StatsCollectorForTest stats(&pc_); | |
931 | |
932 StatsReports reports; // returned values. | |
933 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
934 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
935 stats.GetStats(NULL, &reports); | |
936 const StatsReport* session_report = FindNthReportByType( | |
937 reports, StatsReport::kStatsReportTypeSession, 1); | |
938 EXPECT_FALSE(session_report == NULL); | |
939 session_report = FindNthReportByType( | |
940 reports, StatsReport::kStatsReportTypeSession, 2); | |
941 EXPECT_EQ(NULL, session_report); | |
942 } | |
943 | |
944 // This test verifies that the empty track report exists in the returned stats | |
945 // without calling StatsCollector::UpdateStats. | |
946 TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { | |
947 StatsCollectorForTest stats(&pc_); | |
948 | |
949 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
950 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
951 nullptr, "video", false); | |
952 AddOutgoingVideoTrackStats(); | |
953 stats.AddStream(stream_); | |
954 | |
955 // Verfies the existence of the track report. | |
956 StatsReports reports; | |
957 stats.GetStats(NULL, &reports); | |
958 EXPECT_EQ((size_t)1, reports.size()); | |
959 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type()); | |
960 EXPECT_EQ(0, reports[0]->timestamp()); | |
961 | |
962 std::string trackValue = | |
963 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, | |
964 reports, | |
965 StatsReport::kStatsValueNameTrackId); | |
966 EXPECT_EQ(kLocalTrackId, trackValue); | |
967 } | |
968 | |
969 // This test verifies that the empty track report exists in the returned stats | |
970 // when StatsCollector::UpdateStats is called with ssrc stats. | |
971 TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { | |
972 StatsCollectorForTest stats(&pc_); | |
973 | |
974 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
975 .WillRepeatedly(Return(false)); | |
976 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
977 .WillRepeatedly(Return(false)); | |
978 | |
979 const char kVideoChannelName[] = "video"; | |
980 InitSessionStats(kVideoChannelName); | |
981 EXPECT_CALL(session_, GetTransportStats(_)) | |
982 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
983 Return(true))); | |
984 | |
985 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
986 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
987 nullptr, kVideoChannelName, false); | |
988 AddOutgoingVideoTrackStats(); | |
989 stats.AddStream(stream_); | |
990 | |
991 // Constructs an ssrc stats update. | |
992 cricket::VideoSenderInfo video_sender_info; | |
993 cricket::VideoMediaInfo stats_read; | |
994 const int64_t kBytesSent = 12345678901234LL; | |
995 | |
996 // Construct a stats value to read. | |
997 video_sender_info.add_ssrc(1234); | |
998 video_sender_info.bytes_sent = kBytesSent; | |
999 stats_read.senders.push_back(video_sender_info); | |
1000 | |
1001 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1002 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1003 EXPECT_CALL(*media_channel, GetStats(_)) | |
1004 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
1005 Return(true))); | |
1006 | |
1007 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1008 StatsReports reports; | |
1009 stats.GetStats(NULL, &reports); | |
1010 // |reports| should contain at least one session report, one track report, | |
1011 // and one ssrc report. | |
1012 EXPECT_LE((size_t)3, reports.size()); | |
1013 const StatsReport* track_report = FindNthReportByType( | |
1014 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1015 EXPECT_TRUE(track_report); | |
1016 | |
1017 // Get report for the specific |track|. | |
1018 reports.clear(); | |
1019 stats.GetStats(track_, &reports); | |
1020 // |reports| should contain at least one session report, one track report, | |
1021 // and one ssrc report. | |
1022 EXPECT_LE((size_t)3, reports.size()); | |
1023 track_report = FindNthReportByType( | |
1024 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1025 EXPECT_TRUE(track_report); | |
1026 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1027 | |
1028 std::string ssrc_id = ExtractSsrcStatsValue( | |
1029 reports, StatsReport::kStatsValueNameSsrc); | |
1030 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1031 | |
1032 std::string track_id = ExtractSsrcStatsValue( | |
1033 reports, StatsReport::kStatsValueNameTrackId); | |
1034 EXPECT_EQ(kLocalTrackId, track_id); | |
1035 } | |
1036 | |
1037 // This test verifies that an SSRC object has the identifier of a Transport | |
1038 // stats object, and that this transport stats object exists in stats. | |
1039 TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { | |
1040 StatsCollectorForTest stats(&pc_); | |
1041 | |
1042 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1043 .WillRepeatedly(Return(false)); | |
1044 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1045 .WillRepeatedly(Return(false)); | |
1046 | |
1047 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1048 // The transport_name known by the video channel. | |
1049 const std::string kVcName("vcname"); | |
1050 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1051 nullptr, kVcName, false); | |
1052 AddOutgoingVideoTrackStats(); | |
1053 stats.AddStream(stream_); | |
1054 | |
1055 // Constructs an ssrc stats update. | |
1056 cricket::VideoSenderInfo video_sender_info; | |
1057 cricket::VideoMediaInfo stats_read; | |
1058 const int64_t kBytesSent = 12345678901234LL; | |
1059 | |
1060 // Construct a stats value to read. | |
1061 video_sender_info.add_ssrc(1234); | |
1062 video_sender_info.bytes_sent = kBytesSent; | |
1063 stats_read.senders.push_back(video_sender_info); | |
1064 | |
1065 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1066 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1067 EXPECT_CALL(*media_channel, GetStats(_)) | |
1068 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1069 Return(true))); | |
1070 | |
1071 InitSessionStats(kVcName); | |
1072 EXPECT_CALL(session_, GetTransportStats(_)) | |
1073 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1074 Return(true))); | |
1075 | |
1076 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1077 StatsReports reports; | |
1078 stats.GetStats(NULL, &reports); | |
1079 std::string transport_id = ExtractStatsValue( | |
1080 StatsReport::kStatsReportTypeSsrc, | |
1081 reports, | |
1082 StatsReport::kStatsValueNameTransportId); | |
1083 ASSERT_NE(kNotFound, transport_id); | |
1084 // Transport id component ID will always be 1. | |
1085 // This has assumptions about how the ID is constructed. As is, this is | |
1086 // OK since this is for testing purposes only, but if we ever need this | |
1087 // in production, we should add a generic method that does this. | |
1088 size_t index = transport_id.find('-'); | |
1089 ASSERT_NE(std::string::npos, index); | |
1090 std::string content = transport_id.substr(index + 1); | |
1091 index = content.rfind('-'); | |
1092 ASSERT_NE(std::string::npos, index); | |
1093 content = content.substr(0, index); | |
1094 StatsReport::Id id(StatsReport::NewComponentId(content, 1)); | |
1095 ASSERT_EQ(transport_id, id->ToString()); | |
1096 const StatsReport* transport_report = FindReportById(reports, id); | |
1097 ASSERT_FALSE(transport_report == NULL); | |
1098 } | |
1099 | |
1100 // This test verifies that a remote stats object will not be created for | |
1101 // an outgoing SSRC where remote stats are not returned. | |
1102 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { | |
1103 StatsCollectorForTest stats(&pc_); | |
1104 | |
1105 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1106 // The transport_name known by the video channel. | |
1107 const std::string kVcName("vcname"); | |
1108 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1109 nullptr, kVcName, false); | |
1110 AddOutgoingVideoTrackStats(); | |
1111 stats.AddStream(stream_); | |
1112 | |
1113 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1114 StatsReports reports; | |
1115 stats.GetStats(NULL, &reports); | |
1116 const StatsReport* remote_report = FindNthReportByType(reports, | |
1117 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1118 EXPECT_TRUE(remote_report == NULL); | |
1119 } | |
1120 | |
1121 // This test verifies that a remote stats object will be created for | |
1122 // an outgoing SSRC where stats are returned. | |
1123 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { | |
1124 StatsCollectorForTest stats(&pc_); | |
1125 | |
1126 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1127 .WillRepeatedly(Return(false)); | |
1128 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1129 .WillRepeatedly(Return(false)); | |
1130 | |
1131 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1132 // The transport_name known by the video channel. | |
1133 const std::string kVcName("vcname"); | |
1134 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1135 nullptr, kVcName, false); | |
1136 AddOutgoingVideoTrackStats(); | |
1137 stats.AddStream(stream_); | |
1138 | |
1139 // Instruct the session to return stats containing the transport channel. | |
1140 InitSessionStats(kVcName); | |
1141 EXPECT_CALL(session_, GetTransportStats(_)) | |
1142 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1143 Return(true))); | |
1144 | |
1145 // Constructs an ssrc stats update. | |
1146 cricket::VideoMediaInfo stats_read; | |
1147 | |
1148 cricket::SsrcReceiverInfo remote_ssrc_stats; | |
1149 remote_ssrc_stats.timestamp = 12345.678; | |
1150 remote_ssrc_stats.ssrc = kSsrcOfTrack; | |
1151 cricket::VideoSenderInfo video_sender_info; | |
1152 video_sender_info.add_ssrc(kSsrcOfTrack); | |
1153 video_sender_info.remote_stats.push_back(remote_ssrc_stats); | |
1154 stats_read.senders.push_back(video_sender_info); | |
1155 | |
1156 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1157 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1158 EXPECT_CALL(*media_channel, GetStats(_)) | |
1159 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1160 Return(true))); | |
1161 | |
1162 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1163 StatsReports reports; | |
1164 stats.GetStats(NULL, &reports); | |
1165 | |
1166 const StatsReport* remote_report = FindNthReportByType(reports, | |
1167 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1168 EXPECT_FALSE(remote_report == NULL); | |
1169 EXPECT_EQ(12345.678, remote_report->timestamp()); | |
1170 } | |
1171 | |
1172 // This test verifies that the empty track report exists in the returned stats | |
1173 // when StatsCollector::UpdateStats is called with ssrc stats. | |
1174 TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) { | |
1175 StatsCollectorForTest stats(&pc_); | |
1176 | |
1177 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1178 .WillRepeatedly(Return(false)); | |
1179 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1180 .WillRepeatedly(Return(false)); | |
1181 | |
1182 const char kVideoChannelName[] = "video"; | |
1183 InitSessionStats(kVideoChannelName); | |
1184 EXPECT_CALL(session_, GetTransportStats(_)) | |
1185 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1186 Return(true))); | |
1187 | |
1188 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1189 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1190 nullptr, kVideoChannelName, false); | |
1191 AddIncomingVideoTrackStats(); | |
1192 stats.AddStream(stream_); | |
1193 | |
1194 // Constructs an ssrc stats update. | |
1195 cricket::VideoReceiverInfo video_receiver_info; | |
1196 cricket::VideoMediaInfo stats_read; | |
1197 const int64_t kNumOfPacketsConcealed = 54321; | |
1198 | |
1199 // Construct a stats value to read. | |
1200 video_receiver_info.add_ssrc(1234); | |
1201 video_receiver_info.packets_concealed = kNumOfPacketsConcealed; | |
1202 stats_read.receivers.push_back(video_receiver_info); | |
1203 | |
1204 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1205 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1206 EXPECT_CALL(*media_channel, GetStats(_)) | |
1207 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
1208 Return(true))); | |
1209 | |
1210 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1211 StatsReports reports; | |
1212 stats.GetStats(NULL, &reports); | |
1213 // |reports| should contain at least one session report, one track report, | |
1214 // and one ssrc report. | |
1215 EXPECT_LE(static_cast<size_t>(3), reports.size()); | |
1216 const StatsReport* track_report = FindNthReportByType( | |
1217 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1218 EXPECT_TRUE(track_report); | |
1219 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1220 | |
1221 std::string ssrc_id = ExtractSsrcStatsValue( | |
1222 reports, StatsReport::kStatsValueNameSsrc); | |
1223 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1224 | |
1225 std::string track_id = ExtractSsrcStatsValue( | |
1226 reports, StatsReport::kStatsValueNameTrackId); | |
1227 EXPECT_EQ(kRemoteTrackId, track_id); | |
1228 } | |
1229 | |
1230 // This test verifies the Ice Candidate report should contain the correct | |
1231 // information from local/remote candidates. | |
1232 TEST_F(StatsCollectorTest, IceCandidateReport) { | |
1233 StatsCollectorForTest stats(&pc_); | |
1234 | |
1235 StatsReports reports; // returned values. | |
1236 | |
1237 const int local_port = 2000; | |
1238 const char local_ip[] = "192.168.0.1"; | |
1239 const int remote_port = 2001; | |
1240 const char remote_ip[] = "192.168.0.2"; | |
1241 | |
1242 rtc::SocketAddress local_address(local_ip, local_port); | |
1243 rtc::SocketAddress remote_address(remote_ip, remote_port); | |
1244 rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; | |
1245 uint32_t priority = 1000; | |
1246 | |
1247 cricket::Candidate c; | |
1248 ASSERT(c.id().length() > 0); | |
1249 c.set_type(cricket::LOCAL_PORT_TYPE); | |
1250 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
1251 c.set_address(local_address); | |
1252 c.set_priority(priority); | |
1253 c.set_network_type(network_type); | |
1254 std::string report_id = AddCandidateReport(&stats, c, true)->id()->ToString(); | |
1255 EXPECT_EQ("Cand-" + c.id(), report_id); | |
1256 | |
1257 c = cricket::Candidate(); | |
1258 ASSERT(c.id().length() > 0); | |
1259 c.set_type(cricket::PRFLX_PORT_TYPE); | |
1260 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
1261 c.set_address(remote_address); | |
1262 c.set_priority(priority); | |
1263 c.set_network_type(network_type); | |
1264 report_id = AddCandidateReport(&stats, c, false)->id()->ToString(); | |
1265 EXPECT_EQ("Cand-" + c.id(), report_id); | |
1266 | |
1267 stats.GetStats(NULL, &reports); | |
1268 | |
1269 // Verify the local candidate report is populated correctly. | |
1270 EXPECT_EQ( | |
1271 local_ip, | |
1272 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1273 StatsReport::kStatsValueNameCandidateIPAddress)); | |
1274 EXPECT_EQ( | |
1275 rtc::ToString<int>(local_port), | |
1276 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1277 StatsReport::kStatsValueNameCandidatePortNumber)); | |
1278 EXPECT_EQ( | |
1279 cricket::UDP_PROTOCOL_NAME, | |
1280 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1281 StatsReport::kStatsValueNameCandidateTransportType)); | |
1282 EXPECT_EQ( | |
1283 rtc::ToString<int>(priority), | |
1284 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1285 StatsReport::kStatsValueNameCandidatePriority)); | |
1286 EXPECT_EQ( | |
1287 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), | |
1288 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1289 StatsReport::kStatsValueNameCandidateType)); | |
1290 EXPECT_EQ( | |
1291 AdapterTypeToStatsType(network_type), | |
1292 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1293 StatsReport::kStatsValueNameCandidateNetworkType)); | |
1294 | |
1295 // Verify the remote candidate report is populated correctly. | |
1296 EXPECT_EQ(remote_ip, | |
1297 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1298 reports, | |
1299 StatsReport::kStatsValueNameCandidateIPAddress)); | |
1300 EXPECT_EQ(rtc::ToString<int>(remote_port), | |
1301 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1302 reports, | |
1303 StatsReport::kStatsValueNameCandidatePortNumber)); | |
1304 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, | |
1305 ExtractStatsValue( | |
1306 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
1307 StatsReport::kStatsValueNameCandidateTransportType)); | |
1308 EXPECT_EQ(rtc::ToString<int>(priority), | |
1309 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1310 reports, | |
1311 StatsReport::kStatsValueNameCandidatePriority)); | |
1312 EXPECT_EQ( | |
1313 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), | |
1314 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1315 reports, StatsReport::kStatsValueNameCandidateType)); | |
1316 EXPECT_EQ(kNotFound, | |
1317 ExtractStatsValue( | |
1318 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
1319 StatsReport::kStatsValueNameCandidateNetworkType)); | |
1320 } | |
1321 | |
1322 // This test verifies that all chained certificates are correctly | |
1323 // reported | |
1324 TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { | |
1325 // Build local certificate chain. | |
1326 std::vector<std::string> local_ders(5); | |
1327 local_ders[0] = "These"; | |
1328 local_ders[1] = "are"; | |
1329 local_ders[2] = "some"; | |
1330 local_ders[3] = "der"; | |
1331 local_ders[4] = "values"; | |
1332 rtc::FakeSSLCertificate local_cert(DersToPems(local_ders)); | |
1333 | |
1334 // Build remote certificate chain | |
1335 std::vector<std::string> remote_ders(4); | |
1336 remote_ders[0] = "A"; | |
1337 remote_ders[1] = "non-"; | |
1338 remote_ders[2] = "intersecting"; | |
1339 remote_ders[3] = "set"; | |
1340 rtc::FakeSSLCertificate remote_cert(DersToPems(remote_ders)); | |
1341 | |
1342 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders); | |
1343 } | |
1344 | |
1345 // This test verifies that all certificates without chains are correctly | |
1346 // reported. | |
1347 TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { | |
1348 // Build local certificate. | |
1349 std::string local_der = "This is the local der."; | |
1350 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
1351 | |
1352 // Build remote certificate. | |
1353 std::string remote_der = "This is somebody else's der."; | |
1354 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
1355 | |
1356 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
1357 remote_cert, std::vector<std::string>(1, remote_der)); | |
1358 } | |
1359 | |
1360 // This test verifies that the stats are generated correctly when no | |
1361 // transport is present. | |
1362 TEST_F(StatsCollectorTest, NoTransport) { | |
1363 StatsCollectorForTest stats(&pc_); | |
1364 | |
1365 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1366 .WillRepeatedly(Return(false)); | |
1367 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1368 .WillRepeatedly(Return(false)); | |
1369 | |
1370 StatsReports reports; // returned values. | |
1371 | |
1372 // Fake stats to process. | |
1373 cricket::TransportChannelStats channel_stats; | |
1374 channel_stats.component = 1; | |
1375 | |
1376 cricket::TransportStats transport_stats; | |
1377 transport_stats.transport_name = "audio"; | |
1378 transport_stats.channel_stats.push_back(channel_stats); | |
1379 | |
1380 SessionStats session_stats; | |
1381 session_stats.transport_stats[transport_stats.transport_name] = | |
1382 transport_stats; | |
1383 | |
1384 // Configure MockWebRtcSession | |
1385 EXPECT_CALL(session_, GetTransportStats(_)) | |
1386 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
1387 Return(true))); | |
1388 | |
1389 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1390 stats.GetStats(NULL, &reports); | |
1391 | |
1392 // Check that the local certificate is absent. | |
1393 std::string local_certificate_id = ExtractStatsValue( | |
1394 StatsReport::kStatsReportTypeComponent, | |
1395 reports, | |
1396 StatsReport::kStatsValueNameLocalCertificateId); | |
1397 ASSERT_EQ(kNotFound, local_certificate_id); | |
1398 | |
1399 // Check that the remote certificate is absent. | |
1400 std::string remote_certificate_id = ExtractStatsValue( | |
1401 StatsReport::kStatsReportTypeComponent, | |
1402 reports, | |
1403 StatsReport::kStatsValueNameRemoteCertificateId); | |
1404 ASSERT_EQ(kNotFound, remote_certificate_id); | |
1405 | |
1406 // Check that the negotiated ciphers are absent. | |
1407 std::string dtls_cipher_suite = | |
1408 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
1409 StatsReport::kStatsValueNameDtlsCipher); | |
1410 ASSERT_EQ(kNotFound, dtls_cipher_suite); | |
1411 std::string srtp_crypto_suite = | |
1412 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
1413 StatsReport::kStatsValueNameSrtpCipher); | |
1414 ASSERT_EQ(kNotFound, srtp_crypto_suite); | |
1415 } | |
1416 | |
1417 // This test verifies that the stats are generated correctly when the transport | |
1418 // does not have any certificates. | |
1419 TEST_F(StatsCollectorTest, NoCertificates) { | |
1420 StatsCollectorForTest stats(&pc_); | |
1421 | |
1422 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1423 .WillRepeatedly(Return(false)); | |
1424 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1425 .WillRepeatedly(Return(false)); | |
1426 | |
1427 StatsReports reports; // returned values. | |
1428 | |
1429 // Fake stats to process. | |
1430 cricket::TransportChannelStats channel_stats; | |
1431 channel_stats.component = 1; | |
1432 | |
1433 cricket::TransportStats transport_stats; | |
1434 transport_stats.transport_name = "audio"; | |
1435 transport_stats.channel_stats.push_back(channel_stats); | |
1436 | |
1437 SessionStats session_stats; | |
1438 session_stats.transport_stats[transport_stats.transport_name] = | |
1439 transport_stats; | |
1440 | |
1441 // Fake transport object. | |
1442 rtc::scoped_ptr<cricket::FakeTransport> transport( | |
1443 new cricket::FakeTransport(transport_stats.transport_name)); | |
1444 | |
1445 // Configure MockWebRtcSession | |
1446 EXPECT_CALL(session_, GetTransportStats(_)) | |
1447 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
1448 Return(true))); | |
1449 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1450 stats.GetStats(NULL, &reports); | |
1451 | |
1452 // Check that the local certificate is absent. | |
1453 std::string local_certificate_id = ExtractStatsValue( | |
1454 StatsReport::kStatsReportTypeComponent, | |
1455 reports, | |
1456 StatsReport::kStatsValueNameLocalCertificateId); | |
1457 ASSERT_EQ(kNotFound, local_certificate_id); | |
1458 | |
1459 // Check that the remote certificate is absent. | |
1460 std::string remote_certificate_id = ExtractStatsValue( | |
1461 StatsReport::kStatsReportTypeComponent, | |
1462 reports, | |
1463 StatsReport::kStatsValueNameRemoteCertificateId); | |
1464 ASSERT_EQ(kNotFound, remote_certificate_id); | |
1465 } | |
1466 | |
1467 // This test verifies that a remote certificate with an unsupported digest | |
1468 // algorithm is correctly ignored. | |
1469 TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { | |
1470 // Build a local certificate. | |
1471 std::string local_der = "This is the local der."; | |
1472 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
1473 | |
1474 // Build a remote certificate with an unsupported digest algorithm. | |
1475 std::string remote_der = "This is somebody else's der."; | |
1476 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
1477 remote_cert.set_digest_algorithm("foobar"); | |
1478 | |
1479 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
1480 remote_cert, std::vector<std::string>()); | |
1481 } | |
1482 | |
1483 // This test verifies that a local stats object can get statistics via | |
1484 // AudioTrackInterface::GetStats() method. | |
1485 TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) { | |
1486 StatsCollectorForTest stats(&pc_); | |
1487 | |
1488 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1489 .WillRepeatedly(Return(false)); | |
1490 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1491 .WillRepeatedly(Return(false)); | |
1492 | |
1493 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1494 // The transport_name known by the voice channel. | |
1495 const std::string kVcName("vcname"); | |
1496 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1497 media_channel, nullptr, kVcName, false); | |
1498 AddOutgoingAudioTrackStats(); | |
1499 stats.AddStream(stream_); | |
1500 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
1501 | |
1502 cricket::VoiceSenderInfo voice_sender_info; | |
1503 InitVoiceSenderInfo(&voice_sender_info); | |
1504 | |
1505 cricket::VoiceMediaInfo stats_read; | |
1506 StatsReports reports; // returned values. | |
1507 SetupAndVerifyAudioTrackStats( | |
1508 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1509 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
1510 | |
1511 // Verify that there is no remote report for the local audio track because | |
1512 // we did not set it up. | |
1513 const StatsReport* remote_report = FindNthReportByType(reports, | |
1514 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1515 EXPECT_TRUE(remote_report == NULL); | |
1516 } | |
1517 | |
1518 // This test verifies that audio receive streams populate stats reports | |
1519 // correctly. | |
1520 TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { | |
1521 StatsCollectorForTest stats(&pc_); | |
1522 | |
1523 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1524 .WillRepeatedly(Return(false)); | |
1525 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1526 .WillRepeatedly(Return(false)); | |
1527 | |
1528 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1529 // The transport_name known by the voice channel. | |
1530 const std::string kVcName("vcname"); | |
1531 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1532 media_channel, nullptr, kVcName, false); | |
1533 AddIncomingAudioTrackStats(); | |
1534 stats.AddStream(stream_); | |
1535 | |
1536 cricket::VoiceReceiverInfo voice_receiver_info; | |
1537 InitVoiceReceiverInfo(&voice_receiver_info); | |
1538 voice_receiver_info.codec_name = "fake_codec"; | |
1539 | |
1540 cricket::VoiceMediaInfo stats_read; | |
1541 StatsReports reports; // returned values. | |
1542 SetupAndVerifyAudioTrackStats( | |
1543 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1544 media_channel, NULL, &voice_receiver_info, &stats_read, &reports); | |
1545 } | |
1546 | |
1547 // This test verifies that a local stats object won't update its statistics | |
1548 // after a RemoveLocalAudioTrack() call. | |
1549 TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) { | |
1550 StatsCollectorForTest stats(&pc_); | |
1551 | |
1552 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1553 .WillRepeatedly(Return(false)); | |
1554 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1555 .WillRepeatedly(Return(false)); | |
1556 | |
1557 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1558 // The transport_name known by the voice channel. | |
1559 const std::string kVcName("vcname"); | |
1560 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1561 media_channel, nullptr, kVcName, false); | |
1562 AddOutgoingAudioTrackStats(); | |
1563 stats.AddStream(stream_); | |
1564 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1565 | |
1566 // Instruct the session to return stats containing the transport channel. | |
1567 InitSessionStats(kVcName); | |
1568 EXPECT_CALL(session_, GetTransportStats(_)) | |
1569 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1570 Return(true))); | |
1571 | |
1572 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1573 cricket::VoiceSenderInfo voice_sender_info; | |
1574 InitVoiceSenderInfo(&voice_sender_info); | |
1575 | |
1576 // Constructs an ssrc stats update. | |
1577 cricket::VoiceMediaInfo stats_read; | |
1578 stats_read.senders.push_back(voice_sender_info); | |
1579 | |
1580 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
1581 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
1582 EXPECT_CALL(*media_channel, GetStats(_)) | |
1583 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1584 Return(true))); | |
1585 | |
1586 StatsReports reports; // returned values. | |
1587 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1588 stats.GetStats(NULL, &reports); | |
1589 | |
1590 // The report will exist since we don't remove them in RemoveStream(). | |
1591 const StatsReport* report = FindNthReportByType( | |
1592 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
1593 EXPECT_FALSE(report == NULL); | |
1594 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
1595 std::string track_id = ExtractSsrcStatsValue( | |
1596 reports, StatsReport::kStatsValueNameTrackId); | |
1597 EXPECT_EQ(kLocalTrackId, track_id); | |
1598 std::string ssrc_id = ExtractSsrcStatsValue( | |
1599 reports, StatsReport::kStatsValueNameSsrc); | |
1600 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1601 | |
1602 // Verifies the values in the track report, no value will be changed by the | |
1603 // AudioTrackInterface::GetSignalValue() and | |
1604 // AudioProcessorInterface::AudioProcessorStats::GetStats(); | |
1605 VerifyVoiceSenderInfoReport(report, voice_sender_info); | |
1606 } | |
1607 | |
1608 // This test verifies that when ongoing and incoming audio tracks are using | |
1609 // the same ssrc, they populate stats reports correctly. | |
1610 TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { | |
1611 StatsCollectorForTest stats(&pc_); | |
1612 | |
1613 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1614 .WillRepeatedly(Return(false)); | |
1615 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1616 .WillRepeatedly(Return(false)); | |
1617 | |
1618 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1619 // The transport_name known by the voice channel. | |
1620 const std::string kVcName("vcname"); | |
1621 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1622 media_channel, nullptr, kVcName, false); | |
1623 | |
1624 // Create a local stream with a local audio track and adds it to the stats. | |
1625 AddOutgoingAudioTrackStats(); | |
1626 stats.AddStream(stream_); | |
1627 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1628 | |
1629 // Create a remote stream with a remote audio track and adds it to the stats. | |
1630 rtc::scoped_refptr<webrtc::MediaStream> remote_stream( | |
1631 webrtc::MediaStream::Create("remotestreamlabel")); | |
1632 rtc::scoped_refptr<FakeAudioTrack> remote_track( | |
1633 new rtc::RefCountedObject<FakeAudioTrack>(kRemoteTrackId)); | |
1634 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) | |
1635 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); | |
1636 remote_stream->AddTrack(remote_track); | |
1637 stats.AddStream(remote_stream); | |
1638 | |
1639 // Instruct the session to return stats containing the transport channel. | |
1640 InitSessionStats(kVcName); | |
1641 EXPECT_CALL(session_, GetTransportStats(_)) | |
1642 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1643 Return(true))); | |
1644 | |
1645 cricket::VoiceSenderInfo voice_sender_info; | |
1646 InitVoiceSenderInfo(&voice_sender_info); | |
1647 | |
1648 // Some of the contents in |voice_sender_info| needs to be updated from the | |
1649 // |audio_track_|. | |
1650 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info); | |
1651 | |
1652 cricket::VoiceReceiverInfo voice_receiver_info; | |
1653 InitVoiceReceiverInfo(&voice_receiver_info); | |
1654 | |
1655 // Constructs an ssrc stats update. | |
1656 cricket::VoiceMediaInfo stats_read; | |
1657 stats_read.senders.push_back(voice_sender_info); | |
1658 stats_read.receivers.push_back(voice_receiver_info); | |
1659 | |
1660 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
1661 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
1662 EXPECT_CALL(*media_channel, GetStats(_)) | |
1663 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1664 Return(true))); | |
1665 | |
1666 StatsReports reports; // returned values. | |
1667 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1668 | |
1669 // Get stats for the local track. | |
1670 stats.GetStats(audio_track_.get(), &reports); | |
1671 const StatsReport* track_report = FindNthReportByType( | |
1672 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
1673 EXPECT_TRUE(track_report); | |
1674 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1675 std::string track_id = ExtractSsrcStatsValue( | |
1676 reports, StatsReport::kStatsValueNameTrackId); | |
1677 EXPECT_EQ(kLocalTrackId, track_id); | |
1678 VerifyVoiceSenderInfoReport(track_report, voice_sender_info); | |
1679 | |
1680 // Get stats for the remote track. | |
1681 reports.clear(); | |
1682 stats.GetStats(remote_track.get(), &reports); | |
1683 track_report = FindNthReportByType(reports, | |
1684 StatsReport::kStatsReportTypeSsrc, 1); | |
1685 EXPECT_TRUE(track_report); | |
1686 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1687 track_id = ExtractSsrcStatsValue(reports, | |
1688 StatsReport::kStatsValueNameTrackId); | |
1689 EXPECT_EQ(kRemoteTrackId, track_id); | |
1690 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info); | |
1691 } | |
1692 | |
1693 // This test verifies that when two outgoing audio tracks are using the same | |
1694 // ssrc at different times, they populate stats reports correctly. | |
1695 // TODO(xians): Figure out if it is possible to encapsulate the setup and | |
1696 // avoid duplication of code in test cases. | |
1697 TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { | |
1698 StatsCollectorForTest stats(&pc_); | |
1699 | |
1700 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1701 .WillRepeatedly(Return(false)); | |
1702 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1703 .WillRepeatedly(Return(false)); | |
1704 | |
1705 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1706 // The transport_name known by the voice channel. | |
1707 const std::string kVcName("vcname"); | |
1708 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1709 media_channel, nullptr, kVcName, false); | |
1710 | |
1711 // Create a local stream with a local audio track and adds it to the stats. | |
1712 AddOutgoingAudioTrackStats(); | |
1713 stats.AddStream(stream_); | |
1714 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
1715 | |
1716 cricket::VoiceSenderInfo voice_sender_info; | |
1717 voice_sender_info.add_ssrc(kSsrcOfTrack); | |
1718 | |
1719 cricket::VoiceMediaInfo stats_read; | |
1720 StatsReports reports; // returned values. | |
1721 SetupAndVerifyAudioTrackStats( | |
1722 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1723 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
1724 | |
1725 // Remove the previous audio track from the stream. | |
1726 stream_->RemoveTrack(audio_track_.get()); | |
1727 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1728 | |
1729 // Create a new audio track and adds it to the stream and stats. | |
1730 static const std::string kNewTrackId = "new_track_id"; | |
1731 rtc::scoped_refptr<FakeAudioTrack> new_audio_track( | |
1732 new rtc::RefCountedObject<FakeAudioTrack>(kNewTrackId)); | |
1733 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) | |
1734 .WillOnce(DoAll(SetArgPointee<1>(kNewTrackId), Return(true))); | |
1735 stream_->AddTrack(new_audio_track); | |
1736 | |
1737 stats.AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); | |
1738 stats.ClearUpdateStatsCacheForTest(); | |
1739 cricket::VoiceSenderInfo new_voice_sender_info; | |
1740 InitVoiceSenderInfo(&new_voice_sender_info); | |
1741 cricket::VoiceMediaInfo new_stats_read; | |
1742 reports.clear(); | |
1743 SetupAndVerifyAudioTrackStats( | |
1744 new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1745 media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); | |
1746 } | |
1747 | |
1748 } // namespace webrtc | |
OLD | NEW |