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/mediastream.h" | |
35 #include "talk/app/webrtc/mediastreaminterface.h" | |
36 #include "talk/app/webrtc/mediastreamtrack.h" | |
37 #include "talk/app/webrtc/peerconnection.h" | |
38 #include "talk/app/webrtc/peerconnectionfactory.h" | |
39 #include "talk/app/webrtc/test/fakedatachannelprovider.h" | |
40 #include "talk/app/webrtc/videotrack.h" | |
41 #include "talk/session/media/channelmanager.h" | |
42 #include "testing/gmock/include/gmock/gmock.h" | |
43 #include "testing/gtest/include/gtest/gtest.h" | |
44 #include "webrtc/base/base64.h" | |
45 #include "webrtc/base/fakesslidentity.h" | |
46 #include "webrtc/base/gunit.h" | |
47 #include "webrtc/base/network.h" | |
48 #include "webrtc/media/base/fakemediaengine.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 std::string media_type = ExtractSsrcStatsValue(*reports, | |
647 StatsReport::kStatsValueNameMediaType); | |
648 EXPECT_EQ("audio", media_type); | |
649 | |
650 // Verifies the values in the track report. | |
651 if (voice_sender_info) { | |
652 UpdateVoiceSenderInfoFromAudioTrack(audio_track, voice_sender_info); | |
653 VerifyVoiceSenderInfoReport(report, *voice_sender_info); | |
654 } | |
655 if (voice_receiver_info) { | |
656 VerifyVoiceReceiverInfoReport(report, *voice_receiver_info); | |
657 } | |
658 | |
659 // Verify we get the same result by passing a track to GetStats(). | |
660 StatsReports track_reports; // returned values. | |
661 stats->GetStats(audio_track, &track_reports); | |
662 const StatsReport* track_report = FindNthReportByType( | |
663 track_reports, StatsReport::kStatsReportTypeSsrc, 1); | |
664 EXPECT_TRUE(track_report); | |
665 EXPECT_EQ(stats->GetTimeNow(), track_report->timestamp()); | |
666 track_id = ExtractSsrcStatsValue(track_reports, | |
667 StatsReport::kStatsValueNameTrackId); | |
668 EXPECT_EQ(audio_track->id(), track_id); | |
669 ssrc_id = ExtractSsrcStatsValue(track_reports, | |
670 StatsReport::kStatsValueNameSsrc); | |
671 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
672 if (voice_sender_info) | |
673 VerifyVoiceSenderInfoReport(track_report, *voice_sender_info); | |
674 if (voice_receiver_info) | |
675 VerifyVoiceReceiverInfoReport(track_report, *voice_receiver_info); | |
676 } | |
677 | |
678 void TestCertificateReports(const rtc::FakeSSLCertificate& local_cert, | |
679 const std::vector<std::string>& local_ders, | |
680 const rtc::FakeSSLCertificate& remote_cert, | |
681 const std::vector<std::string>& remote_ders) { | |
682 StatsCollectorForTest stats(&pc_); | |
683 | |
684 StatsReports reports; // returned values. | |
685 | |
686 // Fake stats to process. | |
687 cricket::TransportChannelStats channel_stats; | |
688 channel_stats.component = 1; | |
689 channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; | |
690 channel_stats.ssl_cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; | |
691 | |
692 cricket::TransportStats transport_stats; | |
693 transport_stats.transport_name = "audio"; | |
694 transport_stats.channel_stats.push_back(channel_stats); | |
695 | |
696 SessionStats session_stats; | |
697 session_stats.transport_stats[transport_stats.transport_name] = | |
698 transport_stats; | |
699 | |
700 // Fake certificate to report | |
701 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate( | |
702 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::FakeSSLIdentity>( | |
703 new rtc::FakeSSLIdentity(local_cert)))); | |
704 | |
705 // Configure MockWebRtcSession | |
706 EXPECT_CALL(session_, | |
707 GetLocalCertificate(transport_stats.transport_name, _)) | |
708 .WillOnce(DoAll(SetArgPointee<1>(local_certificate), Return(true))); | |
709 EXPECT_CALL(session_, | |
710 GetRemoteSSLCertificate(transport_stats.transport_name, _)) | |
711 .WillOnce( | |
712 DoAll(SetArgPointee<1>(remote_cert.GetReference()), Return(true))); | |
713 EXPECT_CALL(session_, GetTransportStats(_)) | |
714 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
715 Return(true))); | |
716 | |
717 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
718 | |
719 stats.GetStats(NULL, &reports); | |
720 | |
721 const StatsReport* channel_report = FindNthReportByType( | |
722 reports, StatsReport::kStatsReportTypeComponent, 1); | |
723 EXPECT_TRUE(channel_report != NULL); | |
724 | |
725 // Check local certificate chain. | |
726 std::string local_certificate_id = ExtractStatsValue( | |
727 StatsReport::kStatsReportTypeComponent, | |
728 reports, | |
729 StatsReport::kStatsValueNameLocalCertificateId); | |
730 if (local_ders.size() > 0) { | |
731 EXPECT_NE(kNotFound, local_certificate_id); | |
732 StatsReport::Id id(IdFromCertIdString(local_certificate_id)); | |
733 CheckCertChainReports(reports, local_ders, id); | |
734 } else { | |
735 EXPECT_EQ(kNotFound, local_certificate_id); | |
736 } | |
737 | |
738 // Check remote certificate chain. | |
739 std::string remote_certificate_id = ExtractStatsValue( | |
740 StatsReport::kStatsReportTypeComponent, | |
741 reports, | |
742 StatsReport::kStatsValueNameRemoteCertificateId); | |
743 if (remote_ders.size() > 0) { | |
744 EXPECT_NE(kNotFound, remote_certificate_id); | |
745 StatsReport::Id id(IdFromCertIdString(remote_certificate_id)); | |
746 CheckCertChainReports(reports, remote_ders, id); | |
747 } else { | |
748 EXPECT_EQ(kNotFound, remote_certificate_id); | |
749 } | |
750 | |
751 // Check negotiated ciphers. | |
752 std::string dtls_cipher_suite = | |
753 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
754 StatsReport::kStatsValueNameDtlsCipher); | |
755 EXPECT_EQ(rtc::SSLStreamAdapter::SslCipherSuiteToName( | |
756 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), | |
757 dtls_cipher_suite); | |
758 std::string srtp_crypto_suite = | |
759 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
760 StatsReport::kStatsValueNameSrtpCipher); | |
761 EXPECT_EQ(rtc::SrtpCryptoSuiteToName(rtc::SRTP_AES128_CM_SHA1_80), | |
762 srtp_crypto_suite); | |
763 } | |
764 | |
765 cricket::FakeMediaEngine* media_engine_; | |
766 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; | |
767 rtc::scoped_ptr<webrtc::MediaControllerInterface> media_controller_; | |
768 MockWebRtcSession session_; | |
769 MockPeerConnection pc_; | |
770 FakeDataChannelProvider data_channel_provider_; | |
771 SessionStats session_stats_; | |
772 rtc::scoped_refptr<webrtc::MediaStream> stream_; | |
773 rtc::scoped_refptr<webrtc::VideoTrack> track_; | |
774 rtc::scoped_refptr<FakeAudioTrack> audio_track_; | |
775 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; | |
776 }; | |
777 | |
778 // Verify that ExtractDataInfo populates reports. | |
779 TEST_F(StatsCollectorTest, ExtractDataInfo) { | |
780 const std::string label = "hacks"; | |
781 const int id = 31337; | |
782 const std::string state = DataChannelInterface::DataStateString( | |
783 DataChannelInterface::DataState::kConnecting); | |
784 | |
785 AddDataChannel(cricket::DCT_SCTP, label, id); | |
786 StatsCollectorForTest stats(&pc_); | |
787 | |
788 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
789 | |
790 StatsReports reports; | |
791 stats.GetStats(NULL, &reports); | |
792 | |
793 const StatsReport* report = | |
794 FindNthReportByType(reports, StatsReport::kStatsReportTypeDataChannel, 1); | |
795 | |
796 StatsReport::Id reportId = StatsReport::NewTypedIntId( | |
797 StatsReport::kStatsReportTypeDataChannel, id); | |
798 | |
799 EXPECT_TRUE(reportId->Equals(report->id())); | |
800 | |
801 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
802 EXPECT_EQ(label, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
803 reports, | |
804 StatsReport::kStatsValueNameLabel)); | |
805 EXPECT_EQ(rtc::ToString<int64_t>(id), | |
806 ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, reports, | |
807 StatsReport::kStatsValueNameDataChannelId)); | |
808 EXPECT_EQ(state, ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
809 reports, | |
810 StatsReport::kStatsValueNameState)); | |
811 EXPECT_EQ("", ExtractStatsValue(StatsReport::kStatsReportTypeDataChannel, | |
812 reports, | |
813 StatsReport::kStatsValueNameProtocol)); | |
814 } | |
815 | |
816 // This test verifies that 64-bit counters are passed successfully. | |
817 TEST_F(StatsCollectorTest, BytesCounterHandles64Bits) { | |
818 StatsCollectorForTest stats(&pc_); | |
819 | |
820 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
821 .WillRepeatedly(Return(false)); | |
822 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
823 .WillRepeatedly(Return(false)); | |
824 | |
825 const char kVideoChannelName[] = "video"; | |
826 | |
827 InitSessionStats(kVideoChannelName); | |
828 EXPECT_CALL(session_, GetTransportStats(_)) | |
829 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
830 Return(true))); | |
831 | |
832 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
833 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
834 nullptr, kVideoChannelName, false); | |
835 StatsReports reports; // returned values. | |
836 cricket::VideoSenderInfo video_sender_info; | |
837 cricket::VideoMediaInfo stats_read; | |
838 // The number of bytes must be larger than 0xFFFFFFFF for this test. | |
839 const int64_t kBytesSent = 12345678901234LL; | |
840 const std::string kBytesSentString("12345678901234"); | |
841 | |
842 AddOutgoingVideoTrackStats(); | |
843 stats.AddStream(stream_); | |
844 | |
845 // Construct a stats value to read. | |
846 video_sender_info.add_ssrc(1234); | |
847 video_sender_info.bytes_sent = kBytesSent; | |
848 stats_read.senders.push_back(video_sender_info); | |
849 | |
850 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
851 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
852 EXPECT_CALL(*media_channel, GetStats(_)) | |
853 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
854 Return(true))); | |
855 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
856 stats.GetStats(NULL, &reports); | |
857 std::string result = ExtractSsrcStatsValue(reports, | |
858 StatsReport::kStatsValueNameBytesSent); | |
859 EXPECT_EQ(kBytesSentString, result); | |
860 } | |
861 | |
862 // Test that BWE information is reported via stats. | |
863 TEST_F(StatsCollectorTest, BandwidthEstimationInfoIsReported) { | |
864 StatsCollectorForTest stats(&pc_); | |
865 | |
866 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
867 .WillRepeatedly(Return(false)); | |
868 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
869 .WillRepeatedly(Return(false)); | |
870 | |
871 const char kVideoChannelName[] = "video"; | |
872 | |
873 InitSessionStats(kVideoChannelName); | |
874 EXPECT_CALL(session_, GetTransportStats(_)) | |
875 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
876 Return(true))); | |
877 | |
878 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
879 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
880 nullptr, kVideoChannelName, false); | |
881 | |
882 StatsReports reports; // returned values. | |
883 cricket::VideoSenderInfo video_sender_info; | |
884 cricket::VideoMediaInfo stats_read; | |
885 // Set up an SSRC just to test that we get both kinds of stats back: SSRC and | |
886 // BWE. | |
887 const int64_t kBytesSent = 12345678901234LL; | |
888 const std::string kBytesSentString("12345678901234"); | |
889 | |
890 AddOutgoingVideoTrackStats(); | |
891 stats.AddStream(stream_); | |
892 | |
893 // Construct a stats value to read. | |
894 video_sender_info.add_ssrc(1234); | |
895 video_sender_info.bytes_sent = kBytesSent; | |
896 stats_read.senders.push_back(video_sender_info); | |
897 cricket::BandwidthEstimationInfo bwe; | |
898 const int kTargetEncBitrate = 123456; | |
899 const std::string kTargetEncBitrateString("123456"); | |
900 bwe.target_enc_bitrate = kTargetEncBitrate; | |
901 stats_read.bw_estimations.push_back(bwe); | |
902 | |
903 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
904 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
905 EXPECT_CALL(*media_channel, GetStats(_)) | |
906 .WillOnce(DoAll(SetArgPointee<0>(stats_read), Return(true))); | |
907 | |
908 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
909 stats.GetStats(NULL, &reports); | |
910 std::string result = ExtractSsrcStatsValue(reports, | |
911 StatsReport::kStatsValueNameBytesSent); | |
912 EXPECT_EQ(kBytesSentString, result); | |
913 result = ExtractBweStatsValue(reports, | |
914 StatsReport::kStatsValueNameTargetEncBitrate); | |
915 EXPECT_EQ(kTargetEncBitrateString, result); | |
916 } | |
917 | |
918 // This test verifies that an object of type "googSession" always | |
919 // exists in the returned stats. | |
920 TEST_F(StatsCollectorTest, SessionObjectExists) { | |
921 StatsCollectorForTest stats(&pc_); | |
922 | |
923 StatsReports reports; // returned values. | |
924 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
925 stats.GetStats(NULL, &reports); | |
926 const StatsReport* session_report = FindNthReportByType( | |
927 reports, StatsReport::kStatsReportTypeSession, 1); | |
928 EXPECT_FALSE(session_report == NULL); | |
929 } | |
930 | |
931 // This test verifies that only one object of type "googSession" exists | |
932 // in the returned stats. | |
933 TEST_F(StatsCollectorTest, OnlyOneSessionObjectExists) { | |
934 StatsCollectorForTest stats(&pc_); | |
935 | |
936 StatsReports reports; // returned values. | |
937 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
938 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
939 stats.GetStats(NULL, &reports); | |
940 const StatsReport* session_report = FindNthReportByType( | |
941 reports, StatsReport::kStatsReportTypeSession, 1); | |
942 EXPECT_FALSE(session_report == NULL); | |
943 session_report = FindNthReportByType( | |
944 reports, StatsReport::kStatsReportTypeSession, 2); | |
945 EXPECT_EQ(NULL, session_report); | |
946 } | |
947 | |
948 // This test verifies that the empty track report exists in the returned stats | |
949 // without calling StatsCollector::UpdateStats. | |
950 TEST_F(StatsCollectorTest, TrackObjectExistsWithoutUpdateStats) { | |
951 StatsCollectorForTest stats(&pc_); | |
952 | |
953 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
954 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
955 nullptr, "video", false); | |
956 AddOutgoingVideoTrackStats(); | |
957 stats.AddStream(stream_); | |
958 | |
959 // Verfies the existence of the track report. | |
960 StatsReports reports; | |
961 stats.GetStats(NULL, &reports); | |
962 EXPECT_EQ((size_t)1, reports.size()); | |
963 EXPECT_EQ(StatsReport::kStatsReportTypeTrack, reports[0]->type()); | |
964 EXPECT_EQ(0, reports[0]->timestamp()); | |
965 | |
966 std::string trackValue = | |
967 ExtractStatsValue(StatsReport::kStatsReportTypeTrack, | |
968 reports, | |
969 StatsReport::kStatsValueNameTrackId); | |
970 EXPECT_EQ(kLocalTrackId, trackValue); | |
971 } | |
972 | |
973 // This test verifies that the empty track report exists in the returned stats | |
974 // when StatsCollector::UpdateStats is called with ssrc stats. | |
975 TEST_F(StatsCollectorTest, TrackAndSsrcObjectExistAfterUpdateSsrcStats) { | |
976 StatsCollectorForTest stats(&pc_); | |
977 | |
978 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
979 .WillRepeatedly(Return(false)); | |
980 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
981 .WillRepeatedly(Return(false)); | |
982 | |
983 const char kVideoChannelName[] = "video"; | |
984 InitSessionStats(kVideoChannelName); | |
985 EXPECT_CALL(session_, GetTransportStats(_)) | |
986 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
987 Return(true))); | |
988 | |
989 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
990 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
991 nullptr, kVideoChannelName, false); | |
992 AddOutgoingVideoTrackStats(); | |
993 stats.AddStream(stream_); | |
994 | |
995 // Constructs an ssrc stats update. | |
996 cricket::VideoSenderInfo video_sender_info; | |
997 cricket::VideoMediaInfo stats_read; | |
998 const int64_t kBytesSent = 12345678901234LL; | |
999 | |
1000 // Construct a stats value to read. | |
1001 video_sender_info.add_ssrc(1234); | |
1002 video_sender_info.bytes_sent = kBytesSent; | |
1003 stats_read.senders.push_back(video_sender_info); | |
1004 | |
1005 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1006 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1007 EXPECT_CALL(*media_channel, GetStats(_)) | |
1008 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
1009 Return(true))); | |
1010 | |
1011 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1012 StatsReports reports; | |
1013 stats.GetStats(NULL, &reports); | |
1014 // |reports| should contain at least one session report, one track report, | |
1015 // and one ssrc report. | |
1016 EXPECT_LE((size_t)3, reports.size()); | |
1017 const StatsReport* track_report = FindNthReportByType( | |
1018 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1019 EXPECT_TRUE(track_report); | |
1020 | |
1021 // Get report for the specific |track|. | |
1022 reports.clear(); | |
1023 stats.GetStats(track_, &reports); | |
1024 // |reports| should contain at least one session report, one track report, | |
1025 // and one ssrc report. | |
1026 EXPECT_LE((size_t)3, reports.size()); | |
1027 track_report = FindNthReportByType( | |
1028 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1029 EXPECT_TRUE(track_report); | |
1030 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1031 | |
1032 std::string ssrc_id = ExtractSsrcStatsValue( | |
1033 reports, StatsReport::kStatsValueNameSsrc); | |
1034 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1035 | |
1036 std::string track_id = ExtractSsrcStatsValue( | |
1037 reports, StatsReport::kStatsValueNameTrackId); | |
1038 EXPECT_EQ(kLocalTrackId, track_id); | |
1039 | |
1040 std::string media_type = ExtractSsrcStatsValue(reports, | |
1041 StatsReport::kStatsValueNameMediaType); | |
1042 EXPECT_EQ("video", media_type); | |
1043 } | |
1044 | |
1045 // This test verifies that an SSRC object has the identifier of a Transport | |
1046 // stats object, and that this transport stats object exists in stats. | |
1047 TEST_F(StatsCollectorTest, TransportObjectLinkedFromSsrcObject) { | |
1048 StatsCollectorForTest stats(&pc_); | |
1049 | |
1050 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1051 .WillRepeatedly(Return(false)); | |
1052 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1053 .WillRepeatedly(Return(false)); | |
1054 | |
1055 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1056 // The transport_name known by the video channel. | |
1057 const std::string kVcName("vcname"); | |
1058 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1059 nullptr, kVcName, false); | |
1060 AddOutgoingVideoTrackStats(); | |
1061 stats.AddStream(stream_); | |
1062 | |
1063 // Constructs an ssrc stats update. | |
1064 cricket::VideoSenderInfo video_sender_info; | |
1065 cricket::VideoMediaInfo stats_read; | |
1066 const int64_t kBytesSent = 12345678901234LL; | |
1067 | |
1068 // Construct a stats value to read. | |
1069 video_sender_info.add_ssrc(1234); | |
1070 video_sender_info.bytes_sent = kBytesSent; | |
1071 stats_read.senders.push_back(video_sender_info); | |
1072 | |
1073 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1074 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1075 EXPECT_CALL(*media_channel, GetStats(_)) | |
1076 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1077 Return(true))); | |
1078 | |
1079 InitSessionStats(kVcName); | |
1080 EXPECT_CALL(session_, GetTransportStats(_)) | |
1081 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1082 Return(true))); | |
1083 | |
1084 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1085 StatsReports reports; | |
1086 stats.GetStats(NULL, &reports); | |
1087 std::string transport_id = ExtractStatsValue( | |
1088 StatsReport::kStatsReportTypeSsrc, | |
1089 reports, | |
1090 StatsReport::kStatsValueNameTransportId); | |
1091 ASSERT_NE(kNotFound, transport_id); | |
1092 // Transport id component ID will always be 1. | |
1093 // This has assumptions about how the ID is constructed. As is, this is | |
1094 // OK since this is for testing purposes only, but if we ever need this | |
1095 // in production, we should add a generic method that does this. | |
1096 size_t index = transport_id.find('-'); | |
1097 ASSERT_NE(std::string::npos, index); | |
1098 std::string content = transport_id.substr(index + 1); | |
1099 index = content.rfind('-'); | |
1100 ASSERT_NE(std::string::npos, index); | |
1101 content = content.substr(0, index); | |
1102 StatsReport::Id id(StatsReport::NewComponentId(content, 1)); | |
1103 ASSERT_EQ(transport_id, id->ToString()); | |
1104 const StatsReport* transport_report = FindReportById(reports, id); | |
1105 ASSERT_FALSE(transport_report == NULL); | |
1106 } | |
1107 | |
1108 // This test verifies that a remote stats object will not be created for | |
1109 // an outgoing SSRC where remote stats are not returned. | |
1110 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsAbsent) { | |
1111 StatsCollectorForTest stats(&pc_); | |
1112 | |
1113 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1114 // The transport_name known by the video channel. | |
1115 const std::string kVcName("vcname"); | |
1116 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1117 nullptr, kVcName, false); | |
1118 AddOutgoingVideoTrackStats(); | |
1119 stats.AddStream(stream_); | |
1120 | |
1121 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1122 StatsReports reports; | |
1123 stats.GetStats(NULL, &reports); | |
1124 const StatsReport* remote_report = FindNthReportByType(reports, | |
1125 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1126 EXPECT_TRUE(remote_report == NULL); | |
1127 } | |
1128 | |
1129 // This test verifies that a remote stats object will be created for | |
1130 // an outgoing SSRC where stats are returned. | |
1131 TEST_F(StatsCollectorTest, RemoteSsrcInfoIsPresent) { | |
1132 StatsCollectorForTest stats(&pc_); | |
1133 | |
1134 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1135 .WillRepeatedly(Return(false)); | |
1136 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1137 .WillRepeatedly(Return(false)); | |
1138 | |
1139 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1140 // The transport_name known by the video channel. | |
1141 const std::string kVcName("vcname"); | |
1142 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1143 nullptr, kVcName, false); | |
1144 AddOutgoingVideoTrackStats(); | |
1145 stats.AddStream(stream_); | |
1146 | |
1147 // Instruct the session to return stats containing the transport channel. | |
1148 InitSessionStats(kVcName); | |
1149 EXPECT_CALL(session_, GetTransportStats(_)) | |
1150 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1151 Return(true))); | |
1152 | |
1153 // Constructs an ssrc stats update. | |
1154 cricket::VideoMediaInfo stats_read; | |
1155 | |
1156 cricket::SsrcReceiverInfo remote_ssrc_stats; | |
1157 remote_ssrc_stats.timestamp = 12345.678; | |
1158 remote_ssrc_stats.ssrc = kSsrcOfTrack; | |
1159 cricket::VideoSenderInfo video_sender_info; | |
1160 video_sender_info.add_ssrc(kSsrcOfTrack); | |
1161 video_sender_info.remote_stats.push_back(remote_ssrc_stats); | |
1162 stats_read.senders.push_back(video_sender_info); | |
1163 | |
1164 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1165 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1166 EXPECT_CALL(*media_channel, GetStats(_)) | |
1167 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1168 Return(true))); | |
1169 | |
1170 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1171 StatsReports reports; | |
1172 stats.GetStats(NULL, &reports); | |
1173 | |
1174 const StatsReport* remote_report = FindNthReportByType(reports, | |
1175 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1176 EXPECT_FALSE(remote_report == NULL); | |
1177 EXPECT_EQ(12345.678, remote_report->timestamp()); | |
1178 } | |
1179 | |
1180 // This test verifies that the empty track report exists in the returned stats | |
1181 // when StatsCollector::UpdateStats is called with ssrc stats. | |
1182 TEST_F(StatsCollectorTest, ReportsFromRemoteTrack) { | |
1183 StatsCollectorForTest stats(&pc_); | |
1184 | |
1185 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1186 .WillRepeatedly(Return(false)); | |
1187 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1188 .WillRepeatedly(Return(false)); | |
1189 | |
1190 const char kVideoChannelName[] = "video"; | |
1191 InitSessionStats(kVideoChannelName); | |
1192 EXPECT_CALL(session_, GetTransportStats(_)) | |
1193 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1194 Return(true))); | |
1195 | |
1196 MockVideoMediaChannel* media_channel = new MockVideoMediaChannel(); | |
1197 cricket::VideoChannel video_channel(rtc::Thread::Current(), media_channel, | |
1198 nullptr, kVideoChannelName, false); | |
1199 AddIncomingVideoTrackStats(); | |
1200 stats.AddStream(stream_); | |
1201 | |
1202 // Constructs an ssrc stats update. | |
1203 cricket::VideoReceiverInfo video_receiver_info; | |
1204 cricket::VideoMediaInfo stats_read; | |
1205 const int64_t kNumOfPacketsConcealed = 54321; | |
1206 | |
1207 // Construct a stats value to read. | |
1208 video_receiver_info.add_ssrc(1234); | |
1209 video_receiver_info.packets_concealed = kNumOfPacketsConcealed; | |
1210 stats_read.receivers.push_back(video_receiver_info); | |
1211 | |
1212 EXPECT_CALL(session_, video_channel()).WillRepeatedly(Return(&video_channel)); | |
1213 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
1214 EXPECT_CALL(*media_channel, GetStats(_)) | |
1215 .WillOnce(DoAll(SetArgPointee<0>(stats_read), | |
1216 Return(true))); | |
1217 | |
1218 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1219 StatsReports reports; | |
1220 stats.GetStats(NULL, &reports); | |
1221 // |reports| should contain at least one session report, one track report, | |
1222 // and one ssrc report. | |
1223 EXPECT_LE(static_cast<size_t>(3), reports.size()); | |
1224 const StatsReport* track_report = FindNthReportByType( | |
1225 reports, StatsReport::kStatsReportTypeTrack, 1); | |
1226 EXPECT_TRUE(track_report); | |
1227 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1228 | |
1229 std::string ssrc_id = ExtractSsrcStatsValue( | |
1230 reports, StatsReport::kStatsValueNameSsrc); | |
1231 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1232 | |
1233 std::string track_id = ExtractSsrcStatsValue( | |
1234 reports, StatsReport::kStatsValueNameTrackId); | |
1235 EXPECT_EQ(kRemoteTrackId, track_id); | |
1236 } | |
1237 | |
1238 // This test verifies the Ice Candidate report should contain the correct | |
1239 // information from local/remote candidates. | |
1240 TEST_F(StatsCollectorTest, IceCandidateReport) { | |
1241 StatsCollectorForTest stats(&pc_); | |
1242 | |
1243 StatsReports reports; // returned values. | |
1244 | |
1245 const int local_port = 2000; | |
1246 const char local_ip[] = "192.168.0.1"; | |
1247 const int remote_port = 2001; | |
1248 const char remote_ip[] = "192.168.0.2"; | |
1249 | |
1250 rtc::SocketAddress local_address(local_ip, local_port); | |
1251 rtc::SocketAddress remote_address(remote_ip, remote_port); | |
1252 rtc::AdapterType network_type = rtc::ADAPTER_TYPE_ETHERNET; | |
1253 uint32_t priority = 1000; | |
1254 | |
1255 cricket::Candidate c; | |
1256 ASSERT(c.id().length() > 0); | |
1257 c.set_type(cricket::LOCAL_PORT_TYPE); | |
1258 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
1259 c.set_address(local_address); | |
1260 c.set_priority(priority); | |
1261 c.set_network_type(network_type); | |
1262 std::string report_id = AddCandidateReport(&stats, c, true)->id()->ToString(); | |
1263 EXPECT_EQ("Cand-" + c.id(), report_id); | |
1264 | |
1265 c = cricket::Candidate(); | |
1266 ASSERT(c.id().length() > 0); | |
1267 c.set_type(cricket::PRFLX_PORT_TYPE); | |
1268 c.set_protocol(cricket::UDP_PROTOCOL_NAME); | |
1269 c.set_address(remote_address); | |
1270 c.set_priority(priority); | |
1271 c.set_network_type(network_type); | |
1272 report_id = AddCandidateReport(&stats, c, false)->id()->ToString(); | |
1273 EXPECT_EQ("Cand-" + c.id(), report_id); | |
1274 | |
1275 stats.GetStats(NULL, &reports); | |
1276 | |
1277 // Verify the local candidate report is populated correctly. | |
1278 EXPECT_EQ( | |
1279 local_ip, | |
1280 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1281 StatsReport::kStatsValueNameCandidateIPAddress)); | |
1282 EXPECT_EQ( | |
1283 rtc::ToString<int>(local_port), | |
1284 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1285 StatsReport::kStatsValueNameCandidatePortNumber)); | |
1286 EXPECT_EQ( | |
1287 cricket::UDP_PROTOCOL_NAME, | |
1288 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1289 StatsReport::kStatsValueNameCandidateTransportType)); | |
1290 EXPECT_EQ( | |
1291 rtc::ToString<int>(priority), | |
1292 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1293 StatsReport::kStatsValueNameCandidatePriority)); | |
1294 EXPECT_EQ( | |
1295 IceCandidateTypeToStatsType(cricket::LOCAL_PORT_TYPE), | |
1296 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1297 StatsReport::kStatsValueNameCandidateType)); | |
1298 EXPECT_EQ( | |
1299 AdapterTypeToStatsType(network_type), | |
1300 ExtractStatsValue(StatsReport::kStatsReportTypeIceLocalCandidate, reports, | |
1301 StatsReport::kStatsValueNameCandidateNetworkType)); | |
1302 | |
1303 // Verify the remote candidate report is populated correctly. | |
1304 EXPECT_EQ(remote_ip, | |
1305 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1306 reports, | |
1307 StatsReport::kStatsValueNameCandidateIPAddress)); | |
1308 EXPECT_EQ(rtc::ToString<int>(remote_port), | |
1309 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1310 reports, | |
1311 StatsReport::kStatsValueNameCandidatePortNumber)); | |
1312 EXPECT_EQ(cricket::UDP_PROTOCOL_NAME, | |
1313 ExtractStatsValue( | |
1314 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
1315 StatsReport::kStatsValueNameCandidateTransportType)); | |
1316 EXPECT_EQ(rtc::ToString<int>(priority), | |
1317 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1318 reports, | |
1319 StatsReport::kStatsValueNameCandidatePriority)); | |
1320 EXPECT_EQ( | |
1321 IceCandidateTypeToStatsType(cricket::PRFLX_PORT_TYPE), | |
1322 ExtractStatsValue(StatsReport::kStatsReportTypeIceRemoteCandidate, | |
1323 reports, StatsReport::kStatsValueNameCandidateType)); | |
1324 EXPECT_EQ(kNotFound, | |
1325 ExtractStatsValue( | |
1326 StatsReport::kStatsReportTypeIceRemoteCandidate, reports, | |
1327 StatsReport::kStatsValueNameCandidateNetworkType)); | |
1328 } | |
1329 | |
1330 // This test verifies that all chained certificates are correctly | |
1331 // reported | |
1332 TEST_F(StatsCollectorTest, ChainedCertificateReportsCreated) { | |
1333 // Build local certificate chain. | |
1334 std::vector<std::string> local_ders(5); | |
1335 local_ders[0] = "These"; | |
1336 local_ders[1] = "are"; | |
1337 local_ders[2] = "some"; | |
1338 local_ders[3] = "der"; | |
1339 local_ders[4] = "values"; | |
1340 rtc::FakeSSLCertificate local_cert(DersToPems(local_ders)); | |
1341 | |
1342 // Build remote certificate chain | |
1343 std::vector<std::string> remote_ders(4); | |
1344 remote_ders[0] = "A"; | |
1345 remote_ders[1] = "non-"; | |
1346 remote_ders[2] = "intersecting"; | |
1347 remote_ders[3] = "set"; | |
1348 rtc::FakeSSLCertificate remote_cert(DersToPems(remote_ders)); | |
1349 | |
1350 TestCertificateReports(local_cert, local_ders, remote_cert, remote_ders); | |
1351 } | |
1352 | |
1353 // This test verifies that all certificates without chains are correctly | |
1354 // reported. | |
1355 TEST_F(StatsCollectorTest, ChainlessCertificateReportsCreated) { | |
1356 // Build local certificate. | |
1357 std::string local_der = "This is the local der."; | |
1358 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
1359 | |
1360 // Build remote certificate. | |
1361 std::string remote_der = "This is somebody else's der."; | |
1362 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
1363 | |
1364 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
1365 remote_cert, std::vector<std::string>(1, remote_der)); | |
1366 } | |
1367 | |
1368 // This test verifies that the stats are generated correctly when no | |
1369 // transport is present. | |
1370 TEST_F(StatsCollectorTest, NoTransport) { | |
1371 StatsCollectorForTest stats(&pc_); | |
1372 | |
1373 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1374 .WillRepeatedly(Return(false)); | |
1375 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1376 .WillRepeatedly(Return(false)); | |
1377 | |
1378 StatsReports reports; // returned values. | |
1379 | |
1380 // Fake stats to process. | |
1381 cricket::TransportChannelStats channel_stats; | |
1382 channel_stats.component = 1; | |
1383 | |
1384 cricket::TransportStats transport_stats; | |
1385 transport_stats.transport_name = "audio"; | |
1386 transport_stats.channel_stats.push_back(channel_stats); | |
1387 | |
1388 SessionStats session_stats; | |
1389 session_stats.transport_stats[transport_stats.transport_name] = | |
1390 transport_stats; | |
1391 | |
1392 // Configure MockWebRtcSession | |
1393 EXPECT_CALL(session_, GetTransportStats(_)) | |
1394 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
1395 Return(true))); | |
1396 | |
1397 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1398 stats.GetStats(NULL, &reports); | |
1399 | |
1400 // Check that the local certificate is absent. | |
1401 std::string local_certificate_id = ExtractStatsValue( | |
1402 StatsReport::kStatsReportTypeComponent, | |
1403 reports, | |
1404 StatsReport::kStatsValueNameLocalCertificateId); | |
1405 ASSERT_EQ(kNotFound, local_certificate_id); | |
1406 | |
1407 // Check that the remote certificate is absent. | |
1408 std::string remote_certificate_id = ExtractStatsValue( | |
1409 StatsReport::kStatsReportTypeComponent, | |
1410 reports, | |
1411 StatsReport::kStatsValueNameRemoteCertificateId); | |
1412 ASSERT_EQ(kNotFound, remote_certificate_id); | |
1413 | |
1414 // Check that the negotiated ciphers are absent. | |
1415 std::string dtls_cipher_suite = | |
1416 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
1417 StatsReport::kStatsValueNameDtlsCipher); | |
1418 ASSERT_EQ(kNotFound, dtls_cipher_suite); | |
1419 std::string srtp_crypto_suite = | |
1420 ExtractStatsValue(StatsReport::kStatsReportTypeComponent, reports, | |
1421 StatsReport::kStatsValueNameSrtpCipher); | |
1422 ASSERT_EQ(kNotFound, srtp_crypto_suite); | |
1423 } | |
1424 | |
1425 // This test verifies that the stats are generated correctly when the transport | |
1426 // does not have any certificates. | |
1427 TEST_F(StatsCollectorTest, NoCertificates) { | |
1428 StatsCollectorForTest stats(&pc_); | |
1429 | |
1430 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1431 .WillRepeatedly(Return(false)); | |
1432 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1433 .WillRepeatedly(Return(false)); | |
1434 | |
1435 StatsReports reports; // returned values. | |
1436 | |
1437 // Fake stats to process. | |
1438 cricket::TransportChannelStats channel_stats; | |
1439 channel_stats.component = 1; | |
1440 | |
1441 cricket::TransportStats transport_stats; | |
1442 transport_stats.transport_name = "audio"; | |
1443 transport_stats.channel_stats.push_back(channel_stats); | |
1444 | |
1445 SessionStats session_stats; | |
1446 session_stats.transport_stats[transport_stats.transport_name] = | |
1447 transport_stats; | |
1448 | |
1449 // Fake transport object. | |
1450 rtc::scoped_ptr<cricket::FakeTransport> transport( | |
1451 new cricket::FakeTransport(transport_stats.transport_name)); | |
1452 | |
1453 // Configure MockWebRtcSession | |
1454 EXPECT_CALL(session_, GetTransportStats(_)) | |
1455 .WillOnce(DoAll(SetArgPointee<0>(session_stats), | |
1456 Return(true))); | |
1457 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1458 stats.GetStats(NULL, &reports); | |
1459 | |
1460 // Check that the local certificate is absent. | |
1461 std::string local_certificate_id = ExtractStatsValue( | |
1462 StatsReport::kStatsReportTypeComponent, | |
1463 reports, | |
1464 StatsReport::kStatsValueNameLocalCertificateId); | |
1465 ASSERT_EQ(kNotFound, local_certificate_id); | |
1466 | |
1467 // Check that the remote certificate is absent. | |
1468 std::string remote_certificate_id = ExtractStatsValue( | |
1469 StatsReport::kStatsReportTypeComponent, | |
1470 reports, | |
1471 StatsReport::kStatsValueNameRemoteCertificateId); | |
1472 ASSERT_EQ(kNotFound, remote_certificate_id); | |
1473 } | |
1474 | |
1475 // This test verifies that a remote certificate with an unsupported digest | |
1476 // algorithm is correctly ignored. | |
1477 TEST_F(StatsCollectorTest, UnsupportedDigestIgnored) { | |
1478 // Build a local certificate. | |
1479 std::string local_der = "This is the local der."; | |
1480 rtc::FakeSSLCertificate local_cert(DerToPem(local_der)); | |
1481 | |
1482 // Build a remote certificate with an unsupported digest algorithm. | |
1483 std::string remote_der = "This is somebody else's der."; | |
1484 rtc::FakeSSLCertificate remote_cert(DerToPem(remote_der)); | |
1485 remote_cert.set_digest_algorithm("foobar"); | |
1486 | |
1487 TestCertificateReports(local_cert, std::vector<std::string>(1, local_der), | |
1488 remote_cert, std::vector<std::string>()); | |
1489 } | |
1490 | |
1491 // This test verifies that a local stats object can get statistics via | |
1492 // AudioTrackInterface::GetStats() method. | |
1493 TEST_F(StatsCollectorTest, GetStatsFromLocalAudioTrack) { | |
1494 StatsCollectorForTest stats(&pc_); | |
1495 | |
1496 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1497 .WillRepeatedly(Return(false)); | |
1498 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1499 .WillRepeatedly(Return(false)); | |
1500 | |
1501 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1502 // The transport_name known by the voice channel. | |
1503 const std::string kVcName("vcname"); | |
1504 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1505 media_channel, nullptr, kVcName, false); | |
1506 AddOutgoingAudioTrackStats(); | |
1507 stats.AddStream(stream_); | |
1508 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
1509 | |
1510 cricket::VoiceSenderInfo voice_sender_info; | |
1511 InitVoiceSenderInfo(&voice_sender_info); | |
1512 | |
1513 cricket::VoiceMediaInfo stats_read; | |
1514 StatsReports reports; // returned values. | |
1515 SetupAndVerifyAudioTrackStats( | |
1516 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1517 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
1518 | |
1519 // Verify that there is no remote report for the local audio track because | |
1520 // we did not set it up. | |
1521 const StatsReport* remote_report = FindNthReportByType(reports, | |
1522 StatsReport::kStatsReportTypeRemoteSsrc, 1); | |
1523 EXPECT_TRUE(remote_report == NULL); | |
1524 } | |
1525 | |
1526 // This test verifies that audio receive streams populate stats reports | |
1527 // correctly. | |
1528 TEST_F(StatsCollectorTest, GetStatsFromRemoteStream) { | |
1529 StatsCollectorForTest stats(&pc_); | |
1530 | |
1531 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1532 .WillRepeatedly(Return(false)); | |
1533 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1534 .WillRepeatedly(Return(false)); | |
1535 | |
1536 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1537 // The transport_name known by the voice channel. | |
1538 const std::string kVcName("vcname"); | |
1539 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1540 media_channel, nullptr, kVcName, false); | |
1541 AddIncomingAudioTrackStats(); | |
1542 stats.AddStream(stream_); | |
1543 | |
1544 cricket::VoiceReceiverInfo voice_receiver_info; | |
1545 InitVoiceReceiverInfo(&voice_receiver_info); | |
1546 voice_receiver_info.codec_name = "fake_codec"; | |
1547 | |
1548 cricket::VoiceMediaInfo stats_read; | |
1549 StatsReports reports; // returned values. | |
1550 SetupAndVerifyAudioTrackStats( | |
1551 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1552 media_channel, NULL, &voice_receiver_info, &stats_read, &reports); | |
1553 } | |
1554 | |
1555 // This test verifies that a local stats object won't update its statistics | |
1556 // after a RemoveLocalAudioTrack() call. | |
1557 TEST_F(StatsCollectorTest, GetStatsAfterRemoveAudioStream) { | |
1558 StatsCollectorForTest stats(&pc_); | |
1559 | |
1560 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1561 .WillRepeatedly(Return(false)); | |
1562 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1563 .WillRepeatedly(Return(false)); | |
1564 | |
1565 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1566 // The transport_name known by the voice channel. | |
1567 const std::string kVcName("vcname"); | |
1568 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1569 media_channel, nullptr, kVcName, false); | |
1570 AddOutgoingAudioTrackStats(); | |
1571 stats.AddStream(stream_); | |
1572 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1573 | |
1574 // Instruct the session to return stats containing the transport channel. | |
1575 InitSessionStats(kVcName); | |
1576 EXPECT_CALL(session_, GetTransportStats(_)) | |
1577 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1578 Return(true))); | |
1579 | |
1580 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1581 cricket::VoiceSenderInfo voice_sender_info; | |
1582 InitVoiceSenderInfo(&voice_sender_info); | |
1583 | |
1584 // Constructs an ssrc stats update. | |
1585 cricket::VoiceMediaInfo stats_read; | |
1586 stats_read.senders.push_back(voice_sender_info); | |
1587 | |
1588 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
1589 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
1590 EXPECT_CALL(*media_channel, GetStats(_)) | |
1591 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1592 Return(true))); | |
1593 | |
1594 StatsReports reports; // returned values. | |
1595 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1596 stats.GetStats(NULL, &reports); | |
1597 | |
1598 // The report will exist since we don't remove them in RemoveStream(). | |
1599 const StatsReport* report = FindNthReportByType( | |
1600 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
1601 EXPECT_FALSE(report == NULL); | |
1602 EXPECT_EQ(stats.GetTimeNow(), report->timestamp()); | |
1603 std::string track_id = ExtractSsrcStatsValue( | |
1604 reports, StatsReport::kStatsValueNameTrackId); | |
1605 EXPECT_EQ(kLocalTrackId, track_id); | |
1606 std::string ssrc_id = ExtractSsrcStatsValue( | |
1607 reports, StatsReport::kStatsValueNameSsrc); | |
1608 EXPECT_EQ(rtc::ToString<uint32_t>(kSsrcOfTrack), ssrc_id); | |
1609 | |
1610 // Verifies the values in the track report, no value will be changed by the | |
1611 // AudioTrackInterface::GetSignalValue() and | |
1612 // AudioProcessorInterface::AudioProcessorStats::GetStats(); | |
1613 VerifyVoiceSenderInfoReport(report, voice_sender_info); | |
1614 } | |
1615 | |
1616 // This test verifies that when ongoing and incoming audio tracks are using | |
1617 // the same ssrc, they populate stats reports correctly. | |
1618 TEST_F(StatsCollectorTest, LocalAndRemoteTracksWithSameSsrc) { | |
1619 StatsCollectorForTest stats(&pc_); | |
1620 | |
1621 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1622 .WillRepeatedly(Return(false)); | |
1623 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1624 .WillRepeatedly(Return(false)); | |
1625 | |
1626 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1627 // The transport_name known by the voice channel. | |
1628 const std::string kVcName("vcname"); | |
1629 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1630 media_channel, nullptr, kVcName, false); | |
1631 | |
1632 // Create a local stream with a local audio track and adds it to the stats. | |
1633 AddOutgoingAudioTrackStats(); | |
1634 stats.AddStream(stream_); | |
1635 stats.AddLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1636 | |
1637 // Create a remote stream with a remote audio track and adds it to the stats. | |
1638 rtc::scoped_refptr<webrtc::MediaStream> remote_stream( | |
1639 webrtc::MediaStream::Create("remotestreamlabel")); | |
1640 rtc::scoped_refptr<FakeAudioTrack> remote_track( | |
1641 new rtc::RefCountedObject<FakeAudioTrack>(kRemoteTrackId)); | |
1642 EXPECT_CALL(session_, GetRemoteTrackIdBySsrc(kSsrcOfTrack, _)) | |
1643 .WillOnce(DoAll(SetArgPointee<1>(kRemoteTrackId), Return(true))); | |
1644 remote_stream->AddTrack(remote_track); | |
1645 stats.AddStream(remote_stream); | |
1646 | |
1647 // Instruct the session to return stats containing the transport channel. | |
1648 InitSessionStats(kVcName); | |
1649 EXPECT_CALL(session_, GetTransportStats(_)) | |
1650 .WillRepeatedly(DoAll(SetArgPointee<0>(session_stats_), | |
1651 Return(true))); | |
1652 | |
1653 cricket::VoiceSenderInfo voice_sender_info; | |
1654 InitVoiceSenderInfo(&voice_sender_info); | |
1655 | |
1656 // Some of the contents in |voice_sender_info| needs to be updated from the | |
1657 // |audio_track_|. | |
1658 UpdateVoiceSenderInfoFromAudioTrack(audio_track_.get(), &voice_sender_info); | |
1659 | |
1660 cricket::VoiceReceiverInfo voice_receiver_info; | |
1661 InitVoiceReceiverInfo(&voice_receiver_info); | |
1662 | |
1663 // Constructs an ssrc stats update. | |
1664 cricket::VoiceMediaInfo stats_read; | |
1665 stats_read.senders.push_back(voice_sender_info); | |
1666 stats_read.receivers.push_back(voice_receiver_info); | |
1667 | |
1668 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(Return(&voice_channel)); | |
1669 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
1670 EXPECT_CALL(*media_channel, GetStats(_)) | |
1671 .WillRepeatedly(DoAll(SetArgPointee<0>(stats_read), | |
1672 Return(true))); | |
1673 | |
1674 StatsReports reports; // returned values. | |
1675 stats.UpdateStats(PeerConnectionInterface::kStatsOutputLevelStandard); | |
1676 | |
1677 // Get stats for the local track. | |
1678 stats.GetStats(audio_track_.get(), &reports); | |
1679 const StatsReport* track_report = FindNthReportByType( | |
1680 reports, StatsReport::kStatsReportTypeSsrc, 1); | |
1681 EXPECT_TRUE(track_report); | |
1682 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1683 std::string track_id = ExtractSsrcStatsValue( | |
1684 reports, StatsReport::kStatsValueNameTrackId); | |
1685 EXPECT_EQ(kLocalTrackId, track_id); | |
1686 VerifyVoiceSenderInfoReport(track_report, voice_sender_info); | |
1687 | |
1688 // Get stats for the remote track. | |
1689 reports.clear(); | |
1690 stats.GetStats(remote_track.get(), &reports); | |
1691 track_report = FindNthReportByType(reports, | |
1692 StatsReport::kStatsReportTypeSsrc, 1); | |
1693 EXPECT_TRUE(track_report); | |
1694 EXPECT_EQ(stats.GetTimeNow(), track_report->timestamp()); | |
1695 track_id = ExtractSsrcStatsValue(reports, | |
1696 StatsReport::kStatsValueNameTrackId); | |
1697 EXPECT_EQ(kRemoteTrackId, track_id); | |
1698 VerifyVoiceReceiverInfoReport(track_report, voice_receiver_info); | |
1699 } | |
1700 | |
1701 // This test verifies that when two outgoing audio tracks are using the same | |
1702 // ssrc at different times, they populate stats reports correctly. | |
1703 // TODO(xians): Figure out if it is possible to encapsulate the setup and | |
1704 // avoid duplication of code in test cases. | |
1705 TEST_F(StatsCollectorTest, TwoLocalTracksWithSameSsrc) { | |
1706 StatsCollectorForTest stats(&pc_); | |
1707 | |
1708 EXPECT_CALL(session_, GetLocalCertificate(_, _)) | |
1709 .WillRepeatedly(Return(false)); | |
1710 EXPECT_CALL(session_, GetRemoteSSLCertificate(_, _)) | |
1711 .WillRepeatedly(Return(false)); | |
1712 | |
1713 MockVoiceMediaChannel* media_channel = new MockVoiceMediaChannel(); | |
1714 // The transport_name known by the voice channel. | |
1715 const std::string kVcName("vcname"); | |
1716 cricket::VoiceChannel voice_channel(rtc::Thread::Current(), media_engine_, | |
1717 media_channel, nullptr, kVcName, false); | |
1718 | |
1719 // Create a local stream with a local audio track and adds it to the stats. | |
1720 AddOutgoingAudioTrackStats(); | |
1721 stats.AddStream(stream_); | |
1722 stats.AddLocalAudioTrack(audio_track_, kSsrcOfTrack); | |
1723 | |
1724 cricket::VoiceSenderInfo voice_sender_info; | |
1725 voice_sender_info.add_ssrc(kSsrcOfTrack); | |
1726 | |
1727 cricket::VoiceMediaInfo stats_read; | |
1728 StatsReports reports; // returned values. | |
1729 SetupAndVerifyAudioTrackStats( | |
1730 audio_track_.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1731 media_channel, &voice_sender_info, NULL, &stats_read, &reports); | |
1732 | |
1733 // Remove the previous audio track from the stream. | |
1734 stream_->RemoveTrack(audio_track_.get()); | |
1735 stats.RemoveLocalAudioTrack(audio_track_.get(), kSsrcOfTrack); | |
1736 | |
1737 // Create a new audio track and adds it to the stream and stats. | |
1738 static const std::string kNewTrackId = "new_track_id"; | |
1739 rtc::scoped_refptr<FakeAudioTrack> new_audio_track( | |
1740 new rtc::RefCountedObject<FakeAudioTrack>(kNewTrackId)); | |
1741 EXPECT_CALL(session_, GetLocalTrackIdBySsrc(kSsrcOfTrack, _)) | |
1742 .WillOnce(DoAll(SetArgPointee<1>(kNewTrackId), Return(true))); | |
1743 stream_->AddTrack(new_audio_track); | |
1744 | |
1745 stats.AddLocalAudioTrack(new_audio_track, kSsrcOfTrack); | |
1746 stats.ClearUpdateStatsCacheForTest(); | |
1747 cricket::VoiceSenderInfo new_voice_sender_info; | |
1748 InitVoiceSenderInfo(&new_voice_sender_info); | |
1749 cricket::VoiceMediaInfo new_stats_read; | |
1750 reports.clear(); | |
1751 SetupAndVerifyAudioTrackStats( | |
1752 new_audio_track.get(), stream_.get(), &stats, &voice_channel, kVcName, | |
1753 media_channel, &new_voice_sender_info, NULL, &new_stats_read, &reports); | |
1754 } | |
1755 | |
1756 } // namespace webrtc | |
OLD | NEW |