OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/api/rtcstatscollector.h" | |
12 | |
13 #include <initializer_list> | |
14 #include <memory> | |
15 #include <ostream> | |
16 #include <string> | |
17 #include <vector> | |
18 | |
19 #include "webrtc/api/jsepsessiondescription.h" | |
20 #include "webrtc/api/mediastream.h" | |
21 #include "webrtc/api/mediastreamtrack.h" | |
22 #include "webrtc/api/rtpparameters.h" | |
23 #include "webrtc/api/stats/rtcstats_objects.h" | |
24 #include "webrtc/api/stats/rtcstatsreport.h" | |
25 #include "webrtc/api/test/mock_datachannel.h" | |
26 #include "webrtc/api/test/mock_peerconnection.h" | |
27 #include "webrtc/api/test/mock_rtpreceiver.h" | |
28 #include "webrtc/api/test/mock_rtpsender.h" | |
29 #include "webrtc/api/test/mock_webrtcsession.h" | |
30 #include "webrtc/api/test/rtcstatsobtainer.h" | |
31 #include "webrtc/base/checks.h" | |
32 #include "webrtc/base/fakeclock.h" | |
33 #include "webrtc/base/fakesslidentity.h" | |
34 #include "webrtc/base/gunit.h" | |
35 #include "webrtc/base/logging.h" | |
36 #include "webrtc/base/socketaddress.h" | |
37 #include "webrtc/base/thread_checker.h" | |
38 #include "webrtc/base/timedelta.h" | |
39 #include "webrtc/base/timeutils.h" | |
40 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | |
41 #include "webrtc/media/base/fakemediaengine.h" | |
42 #include "webrtc/media/base/test/mock_mediachannel.h" | |
43 #include "webrtc/p2p/base/p2pconstants.h" | |
44 #include "webrtc/p2p/base/port.h" | |
45 | |
46 using testing::_; | |
47 using testing::Invoke; | |
48 using testing::Return; | |
49 using testing::ReturnNull; | |
50 using testing::ReturnRef; | |
51 using testing::SetArgPointee; | |
52 | |
53 namespace webrtc { | |
54 | |
55 // These are used by gtest code, such as if |EXPECT_EQ| fails. | |
56 void PrintTo(const RTCCertificateStats& stats, ::std::ostream* os) { | |
57 *os << stats.ToString(); | |
58 } | |
59 | |
60 void PrintTo(const RTCCodecStats& stats, ::std::ostream* os) { | |
61 *os << stats.ToString(); | |
62 } | |
63 | |
64 void PrintTo(const RTCDataChannelStats& stats, ::std::ostream* os) { | |
65 *os << stats.ToString(); | |
66 } | |
67 | |
68 void PrintTo(const RTCIceCandidatePairStats& stats, ::std::ostream* os) { | |
69 *os << stats.ToString(); | |
70 } | |
71 | |
72 void PrintTo(const RTCLocalIceCandidateStats& stats, ::std::ostream* os) { | |
73 *os << stats.ToString(); | |
74 } | |
75 | |
76 void PrintTo(const RTCRemoteIceCandidateStats& stats, ::std::ostream* os) { | |
77 *os << stats.ToString(); | |
78 } | |
79 | |
80 void PrintTo(const RTCPeerConnectionStats& stats, ::std::ostream* os) { | |
81 *os << stats.ToString(); | |
82 } | |
83 | |
84 void PrintTo(const RTCMediaStreamStats& stats, ::std::ostream* os) { | |
85 *os << stats.ToString(); | |
86 } | |
87 | |
88 void PrintTo(const RTCMediaStreamTrackStats& stats, ::std::ostream* os) { | |
89 *os << stats.ToString(); | |
90 } | |
91 | |
92 void PrintTo(const RTCInboundRTPStreamStats& stats, ::std::ostream* os) { | |
93 *os << stats.ToString(); | |
94 } | |
95 | |
96 void PrintTo(const RTCOutboundRTPStreamStats& stats, ::std::ostream* os) { | |
97 *os << stats.ToString(); | |
98 } | |
99 | |
100 void PrintTo(const RTCTransportStats& stats, ::std::ostream* os) { | |
101 *os << stats.ToString(); | |
102 } | |
103 | |
104 namespace { | |
105 | |
106 const int64_t kGetStatsReportTimeoutMs = 1000; | |
107 const bool kDefaultRtcpMuxRequired = true; | |
108 const bool kDefaultSrtpRequired = true; | |
109 | |
110 struct CertificateInfo { | |
111 rtc::scoped_refptr<rtc::RTCCertificate> certificate; | |
112 std::vector<std::string> ders; | |
113 std::vector<std::string> pems; | |
114 std::vector<std::string> fingerprints; | |
115 }; | |
116 | |
117 std::unique_ptr<CertificateInfo> CreateFakeCertificateAndInfoFromDers( | |
118 const std::vector<std::string>& ders) { | |
119 RTC_CHECK(!ders.empty()); | |
120 std::unique_ptr<CertificateInfo> info(new CertificateInfo()); | |
121 info->ders = ders; | |
122 for (const std::string& der : ders) { | |
123 info->pems.push_back(rtc::SSLIdentity::DerToPem( | |
124 "CERTIFICATE", | |
125 reinterpret_cast<const unsigned char*>(der.c_str()), | |
126 der.length())); | |
127 } | |
128 info->certificate = | |
129 rtc::RTCCertificate::Create(std::unique_ptr<rtc::FakeSSLIdentity>( | |
130 new rtc::FakeSSLIdentity(rtc::FakeSSLCertificate(info->pems)))); | |
131 // Strip header/footer and newline characters of PEM strings. | |
132 for (size_t i = 0; i < info->pems.size(); ++i) { | |
133 rtc::replace_substrs("-----BEGIN CERTIFICATE-----", 27, | |
134 "", 0, &info->pems[i]); | |
135 rtc::replace_substrs("-----END CERTIFICATE-----", 25, | |
136 "", 0, &info->pems[i]); | |
137 rtc::replace_substrs("\n", 1, | |
138 "", 0, &info->pems[i]); | |
139 } | |
140 // Fingerprint of leaf certificate. | |
141 std::unique_ptr<rtc::SSLFingerprint> fp( | |
142 rtc::SSLFingerprint::Create("sha-1", | |
143 &info->certificate->ssl_certificate())); | |
144 EXPECT_TRUE(fp); | |
145 info->fingerprints.push_back(fp->GetRfc4572Fingerprint()); | |
146 // Fingerprints of the rest of the chain. | |
147 std::unique_ptr<rtc::SSLCertChain> chain = | |
148 info->certificate->ssl_certificate().GetChain(); | |
149 if (chain) { | |
150 for (size_t i = 0; i < chain->GetSize(); i++) { | |
151 fp.reset(rtc::SSLFingerprint::Create("sha-1", &chain->Get(i))); | |
152 EXPECT_TRUE(fp); | |
153 info->fingerprints.push_back(fp->GetRfc4572Fingerprint()); | |
154 } | |
155 } | |
156 EXPECT_EQ(info->ders.size(), info->fingerprints.size()); | |
157 return info; | |
158 } | |
159 | |
160 std::unique_ptr<cricket::Candidate> CreateFakeCandidate( | |
161 const std::string& hostname, | |
162 int port, | |
163 const std::string& protocol, | |
164 const std::string& candidate_type, | |
165 uint32_t priority) { | |
166 std::unique_ptr<cricket::Candidate> candidate(new cricket::Candidate()); | |
167 candidate->set_address(rtc::SocketAddress(hostname, port)); | |
168 candidate->set_protocol(protocol); | |
169 candidate->set_type(candidate_type); | |
170 candidate->set_priority(priority); | |
171 return candidate; | |
172 } | |
173 | |
174 class FakeAudioTrackForStats | |
175 : public MediaStreamTrack<AudioTrackInterface> { | |
176 public: | |
177 static rtc::scoped_refptr<FakeAudioTrackForStats> Create( | |
178 const std::string& id, | |
179 MediaStreamTrackInterface::TrackState state) { | |
180 rtc::scoped_refptr<FakeAudioTrackForStats> audio_track_stats( | |
181 new rtc::RefCountedObject<FakeAudioTrackForStats>(id)); | |
182 audio_track_stats->set_state(state); | |
183 return audio_track_stats; | |
184 } | |
185 | |
186 FakeAudioTrackForStats(const std::string& id) | |
187 : MediaStreamTrack<AudioTrackInterface>(id) { | |
188 } | |
189 | |
190 std::string kind() const override { | |
191 return MediaStreamTrackInterface::kAudioKind; | |
192 } | |
193 webrtc::AudioSourceInterface* GetSource() const override { return nullptr; } | |
194 void AddSink(webrtc::AudioTrackSinkInterface* sink) override {} | |
195 void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {} | |
196 bool GetSignalLevel(int* level) override { return false; } | |
197 rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor() override { | |
198 return nullptr; | |
199 } | |
200 }; | |
201 | |
202 class FakeVideoTrackForStats | |
203 : public MediaStreamTrack<VideoTrackInterface> { | |
204 public: | |
205 static rtc::scoped_refptr<FakeVideoTrackForStats> Create( | |
206 const std::string& id, | |
207 MediaStreamTrackInterface::TrackState state) { | |
208 rtc::scoped_refptr<FakeVideoTrackForStats> video_track( | |
209 new rtc::RefCountedObject<FakeVideoTrackForStats>(id)); | |
210 video_track->set_state(state); | |
211 return video_track; | |
212 } | |
213 | |
214 FakeVideoTrackForStats(const std::string& id) | |
215 : MediaStreamTrack<VideoTrackInterface>(id) { | |
216 } | |
217 | |
218 std::string kind() const override { | |
219 return MediaStreamTrackInterface::kVideoKind; | |
220 } | |
221 VideoTrackSourceInterface* GetSource() const override { return nullptr; } | |
222 }; | |
223 | |
224 rtc::scoped_refptr<MediaStreamTrackInterface> CreateFakeTrack( | |
225 cricket::MediaType media_type, | |
226 const std::string& track_id, | |
227 MediaStreamTrackInterface::TrackState track_state) { | |
228 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
229 return FakeAudioTrackForStats::Create(track_id, track_state); | |
230 } else { | |
231 RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO); | |
232 return FakeVideoTrackForStats::Create(track_id, track_state); | |
233 } | |
234 } | |
235 | |
236 rtc::scoped_refptr<MockRtpSender> CreateMockSender( | |
237 rtc::scoped_refptr<MediaStreamTrackInterface> track, uint32_t ssrc) { | |
238 rtc::scoped_refptr<MockRtpSender> sender( | |
239 new rtc::RefCountedObject<MockRtpSender>()); | |
240 EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track)); | |
241 EXPECT_CALL(*sender, ssrc()).WillRepeatedly(Return(ssrc)); | |
242 EXPECT_CALL(*sender, media_type()).WillRepeatedly(Return( | |
243 track->kind() == MediaStreamTrackInterface::kAudioKind | |
244 ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO)); | |
245 EXPECT_CALL(*sender, GetParameters()).WillRepeatedly(Invoke( | |
246 [ssrc]() { | |
247 RtpParameters params; | |
248 params.encodings.push_back(RtpEncodingParameters()); | |
249 params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc); | |
250 return params; | |
251 })); | |
252 return sender; | |
253 } | |
254 | |
255 rtc::scoped_refptr<MockRtpReceiver> CreateMockReceiver( | |
256 rtc::scoped_refptr<MediaStreamTrackInterface> track, uint32_t ssrc) { | |
257 rtc::scoped_refptr<MockRtpReceiver> receiver( | |
258 new rtc::RefCountedObject<MockRtpReceiver>()); | |
259 EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track)); | |
260 EXPECT_CALL(*receiver, media_type()).WillRepeatedly(Return( | |
261 track->kind() == MediaStreamTrackInterface::kAudioKind | |
262 ? cricket::MEDIA_TYPE_AUDIO : cricket::MEDIA_TYPE_VIDEO)); | |
263 EXPECT_CALL(*receiver, GetParameters()).WillRepeatedly(Invoke( | |
264 [ssrc]() { | |
265 RtpParameters params; | |
266 params.encodings.push_back(RtpEncodingParameters()); | |
267 params.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc); | |
268 return params; | |
269 })); | |
270 return receiver; | |
271 } | |
272 | |
273 class RTCStatsCollectorTestHelper : public SetSessionDescriptionObserver { | |
274 public: | |
275 RTCStatsCollectorTestHelper() | |
276 : worker_thread_(rtc::Thread::Current()), | |
277 network_thread_(rtc::Thread::Current()), | |
278 signaling_thread_(rtc::Thread::Current()), | |
279 media_engine_(new cricket::FakeMediaEngine()), | |
280 channel_manager_(new cricket::ChannelManager(media_engine_, | |
281 worker_thread_, | |
282 network_thread_)), | |
283 media_controller_( | |
284 MediaControllerInterface::Create(cricket::MediaConfig(), | |
285 worker_thread_, | |
286 channel_manager_.get(), | |
287 &event_log_)), | |
288 session_(media_controller_.get()), | |
289 pc_() { | |
290 // Default return values for mocks. | |
291 EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr)); | |
292 EXPECT_CALL(pc_, remote_streams()).WillRepeatedly(Return(nullptr)); | |
293 EXPECT_CALL(pc_, session()).WillRepeatedly(Return(&session_)); | |
294 EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( | |
295 std::vector<rtc::scoped_refptr<RtpSenderInterface>>())); | |
296 EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( | |
297 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>())); | |
298 EXPECT_CALL(pc_, sctp_data_channels()).WillRepeatedly( | |
299 ReturnRef(data_channels_)); | |
300 EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull()); | |
301 EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull()); | |
302 EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(ReturnNull()); | |
303 EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly( | |
304 Return(false)); | |
305 EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_)) | |
306 .WillRepeatedly(Return(nullptr)); | |
307 } | |
308 | |
309 rtc::ScopedFakeClock& fake_clock() { return fake_clock_; } | |
310 rtc::Thread* worker_thread() { return worker_thread_; } | |
311 rtc::Thread* network_thread() { return network_thread_; } | |
312 rtc::Thread* signaling_thread() { return signaling_thread_; } | |
313 cricket::FakeMediaEngine* media_engine() { return media_engine_; } | |
314 MockWebRtcSession& session() { return session_; } | |
315 MockPeerConnection& pc() { return pc_; } | |
316 std::vector<rtc::scoped_refptr<DataChannel>>& data_channels() { | |
317 return data_channels_; | |
318 } | |
319 | |
320 // SetSessionDescriptionObserver overrides. | |
321 void OnSuccess() override {} | |
322 void OnFailure(const std::string& error) override { | |
323 RTC_NOTREACHED() << error; | |
324 } | |
325 | |
326 void SetupLocalTrackAndSender(cricket::MediaType media_type, | |
327 const std::string& track_id, | |
328 uint32_t ssrc) { | |
329 rtc::scoped_refptr<StreamCollection> local_streams = | |
330 StreamCollection::Create(); | |
331 EXPECT_CALL(pc_, local_streams()) | |
332 .WillRepeatedly(Return(local_streams)); | |
333 | |
334 rtc::scoped_refptr<MediaStream> local_stream = | |
335 MediaStream::Create("LocalStreamLabel"); | |
336 local_streams->AddStream(local_stream); | |
337 | |
338 rtc::scoped_refptr<MediaStreamTrackInterface> track; | |
339 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
340 track = CreateFakeTrack(media_type, track_id, | |
341 MediaStreamTrackInterface::kLive); | |
342 local_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get())); | |
343 } else { | |
344 track = CreateFakeTrack(media_type, track_id, | |
345 MediaStreamTrackInterface::kLive); | |
346 local_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get())); | |
347 } | |
348 | |
349 rtc::scoped_refptr<MockRtpSender> sender = CreateMockSender(track, ssrc); | |
350 EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return( | |
351 std::vector<rtc::scoped_refptr<RtpSenderInterface>>({ | |
352 rtc::scoped_refptr<RtpSenderInterface>(sender.get()) }))); | |
353 } | |
354 | |
355 void SetupRemoteTrackAndReceiver(cricket::MediaType media_type, | |
356 const std::string& track_id, | |
357 uint32_t ssrc) { | |
358 rtc::scoped_refptr<StreamCollection> remote_streams = | |
359 StreamCollection::Create(); | |
360 EXPECT_CALL(pc_, remote_streams()) | |
361 .WillRepeatedly(Return(remote_streams)); | |
362 | |
363 rtc::scoped_refptr<MediaStream> remote_stream = | |
364 MediaStream::Create("RemoteStreamLabel"); | |
365 remote_streams->AddStream(remote_stream); | |
366 | |
367 rtc::scoped_refptr<MediaStreamTrackInterface> track; | |
368 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
369 track = CreateFakeTrack(media_type, track_id, | |
370 MediaStreamTrackInterface::kLive); | |
371 remote_stream->AddTrack(static_cast<AudioTrackInterface*>(track.get())); | |
372 } else { | |
373 track = CreateFakeTrack(media_type, track_id, | |
374 MediaStreamTrackInterface::kLive); | |
375 remote_stream->AddTrack(static_cast<VideoTrackInterface*>(track.get())); | |
376 } | |
377 | |
378 rtc::scoped_refptr<MockRtpReceiver> receiver = | |
379 CreateMockReceiver(track, ssrc); | |
380 EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return( | |
381 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>({ | |
382 rtc::scoped_refptr<RtpReceiverInterface>(receiver.get()) }))); | |
383 } | |
384 | |
385 // Attaches tracks to peer connections by configuring RTP senders and RTP | |
386 // receivers according to the tracks' pairings with | |
387 // |[Voice/Video][Sender/Receiver]Info| and their SSRCs. Local tracks can be | |
388 // associated with multiple |[Voice/Video]SenderInfo|s, remote tracks can only | |
389 // be associated with one |[Voice/Video]ReceiverInfo|. | |
390 void CreateMockRtpSendersReceiversAndChannels( | |
391 std::initializer_list<std::pair<MediaStreamTrackInterface*, | |
392 cricket::VoiceSenderInfo>> local_audio_track_info_pairs, | |
393 std::initializer_list<std::pair<MediaStreamTrackInterface*, | |
394 cricket::VoiceReceiverInfo>> remote_audio_track_info_pairs, | |
395 std::initializer_list<std::pair<MediaStreamTrackInterface*, | |
396 cricket::VideoSenderInfo>> local_video_track_info_pairs, | |
397 std::initializer_list<std::pair<MediaStreamTrackInterface*, | |
398 cricket::VideoReceiverInfo>> remote_video_track_info_pairs) { | |
399 voice_media_info_.reset(new cricket::VoiceMediaInfo()); | |
400 video_media_info_.reset(new cricket::VideoMediaInfo()); | |
401 rtp_senders_.clear(); | |
402 rtp_receivers_.clear(); | |
403 // Local audio tracks and voice sender infos | |
404 for (auto& pair : local_audio_track_info_pairs) { | |
405 MediaStreamTrackInterface* local_audio_track = pair.first; | |
406 const cricket::VoiceSenderInfo& voice_sender_info = pair.second; | |
407 RTC_DCHECK_EQ(local_audio_track->kind(), | |
408 MediaStreamTrackInterface::kAudioKind); | |
409 | |
410 voice_media_info_->senders.push_back(voice_sender_info); | |
411 rtc::scoped_refptr<MockRtpSender> rtp_sender = | |
412 CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>( | |
413 local_audio_track), | |
414 voice_sender_info.local_stats[0].ssrc); | |
415 rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>( | |
416 rtp_sender.get())); | |
417 } | |
418 // Remote audio tracks and voice receiver infos | |
419 for (auto& pair : remote_audio_track_info_pairs) { | |
420 MediaStreamTrackInterface* remote_audio_track = pair.first; | |
421 const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second; | |
422 RTC_DCHECK_EQ(remote_audio_track->kind(), | |
423 MediaStreamTrackInterface::kAudioKind); | |
424 | |
425 voice_media_info_->receivers.push_back(voice_receiver_info); | |
426 rtc::scoped_refptr<MockRtpReceiver> rtp_receiver = | |
427 CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>( | |
428 remote_audio_track), | |
429 voice_receiver_info.local_stats[0].ssrc); | |
430 rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>( | |
431 rtp_receiver.get())); | |
432 } | |
433 // Local video tracks and video sender infos | |
434 for (auto& pair : local_video_track_info_pairs) { | |
435 MediaStreamTrackInterface* local_video_track = pair.first; | |
436 const cricket::VideoSenderInfo& video_sender_info = pair.second; | |
437 RTC_DCHECK_EQ(local_video_track->kind(), | |
438 MediaStreamTrackInterface::kVideoKind); | |
439 | |
440 video_media_info_->senders.push_back(video_sender_info); | |
441 rtc::scoped_refptr<MockRtpSender> rtp_sender = | |
442 CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>( | |
443 local_video_track), | |
444 video_sender_info.local_stats[0].ssrc); | |
445 rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>( | |
446 rtp_sender.get())); | |
447 } | |
448 // Remote video tracks and video receiver infos | |
449 for (auto& pair : remote_video_track_info_pairs) { | |
450 MediaStreamTrackInterface* remote_video_track = pair.first; | |
451 const cricket::VideoReceiverInfo& video_receiver_info = pair.second; | |
452 RTC_DCHECK_EQ(remote_video_track->kind(), | |
453 MediaStreamTrackInterface::kVideoKind); | |
454 | |
455 video_media_info_->receivers.push_back(video_receiver_info); | |
456 rtc::scoped_refptr<MockRtpReceiver> rtp_receiver = | |
457 CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>( | |
458 remote_video_track), | |
459 video_receiver_info.local_stats[0].ssrc); | |
460 rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>( | |
461 rtp_receiver.get())); | |
462 } | |
463 EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return(rtp_senders_)); | |
464 EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return(rtp_receivers_)); | |
465 | |
466 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); | |
467 voice_channel_.reset(new cricket::VoiceChannel( | |
468 worker_thread_, network_thread_, nullptr, media_engine_, | |
469 voice_media_channel, "VoiceContentName", kDefaultRtcpMuxRequired, | |
470 kDefaultSrtpRequired)); | |
471 EXPECT_CALL(session_, voice_channel()) | |
472 .WillRepeatedly(Return(voice_channel_.get())); | |
473 EXPECT_CALL(*voice_media_channel, GetStats(_)) | |
474 .WillOnce(DoAll(SetArgPointee<0>(*voice_media_info_), Return(true))); | |
475 | |
476 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); | |
477 video_channel_.reset(new cricket::VideoChannel( | |
478 worker_thread_, network_thread_, nullptr, video_media_channel, | |
479 "VideoContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired)); | |
480 EXPECT_CALL(session_, video_channel()) | |
481 .WillRepeatedly(Return(video_channel_.get())); | |
482 EXPECT_CALL(*video_media_channel, GetStats(_)) | |
483 .WillOnce(DoAll(SetArgPointee<0>(*video_media_info_), Return(true))); | |
484 } | |
485 | |
486 private: | |
487 rtc::ScopedFakeClock fake_clock_; | |
488 RtcEventLogNullImpl event_log_; | |
489 rtc::Thread* const worker_thread_; | |
490 rtc::Thread* const network_thread_; | |
491 rtc::Thread* const signaling_thread_; | |
492 cricket::FakeMediaEngine* media_engine_; | |
493 std::unique_ptr<cricket::ChannelManager> channel_manager_; | |
494 std::unique_ptr<MediaControllerInterface> media_controller_; | |
495 MockWebRtcSession session_; | |
496 MockPeerConnection pc_; | |
497 | |
498 std::vector<rtc::scoped_refptr<DataChannel>> data_channels_; | |
499 std::unique_ptr<cricket::VoiceChannel> voice_channel_; | |
500 std::unique_ptr<cricket::VideoChannel> video_channel_; | |
501 std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info_; | |
502 std::unique_ptr<cricket::VideoMediaInfo> video_media_info_; | |
503 std::vector<rtc::scoped_refptr<RtpSenderInterface>> rtp_senders_; | |
504 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> rtp_receivers_; | |
505 }; | |
506 | |
507 class RTCTestStats : public RTCStats { | |
508 public: | |
509 WEBRTC_RTCSTATS_DECL(); | |
510 | |
511 RTCTestStats(const std::string& id, int64_t timestamp_us) | |
512 : RTCStats(id, timestamp_us), | |
513 dummy_stat("dummyStat") {} | |
514 | |
515 RTCStatsMember<int32_t> dummy_stat; | |
516 }; | |
517 | |
518 WEBRTC_RTCSTATS_IMPL(RTCTestStats, RTCStats, "test-stats", | |
519 &dummy_stat); | |
520 | |
521 // Overrides the stats collection to verify thread usage and that the resulting | |
522 // partial reports are merged. | |
523 class FakeRTCStatsCollector : public RTCStatsCollector, | |
524 public RTCStatsCollectorCallback { | |
525 public: | |
526 static rtc::scoped_refptr<FakeRTCStatsCollector> Create( | |
527 PeerConnection* pc, | |
528 int64_t cache_lifetime_us) { | |
529 return rtc::scoped_refptr<FakeRTCStatsCollector>( | |
530 new rtc::RefCountedObject<FakeRTCStatsCollector>( | |
531 pc, cache_lifetime_us)); | |
532 } | |
533 | |
534 // RTCStatsCollectorCallback implementation. | |
535 void OnStatsDelivered( | |
536 const rtc::scoped_refptr<const RTCStatsReport>& report) override { | |
537 EXPECT_TRUE(signaling_thread_->IsCurrent()); | |
538 rtc::CritScope cs(&lock_); | |
539 delivered_report_ = report; | |
540 } | |
541 | |
542 void VerifyThreadUsageAndResultsMerging() { | |
543 GetStatsReport(rtc::scoped_refptr<RTCStatsCollectorCallback>(this)); | |
544 EXPECT_TRUE_WAIT(HasVerifiedResults(), kGetStatsReportTimeoutMs); | |
545 } | |
546 | |
547 bool HasVerifiedResults() { | |
548 EXPECT_TRUE(signaling_thread_->IsCurrent()); | |
549 rtc::CritScope cs(&lock_); | |
550 if (!delivered_report_) | |
551 return false; | |
552 EXPECT_EQ(produced_on_signaling_thread_, 1); | |
553 EXPECT_EQ(produced_on_network_thread_, 1); | |
554 | |
555 EXPECT_TRUE(delivered_report_->Get("SignalingThreadStats")); | |
556 EXPECT_TRUE(delivered_report_->Get("NetworkThreadStats")); | |
557 | |
558 produced_on_signaling_thread_ = 0; | |
559 produced_on_network_thread_ = 0; | |
560 delivered_report_ = nullptr; | |
561 return true; | |
562 } | |
563 | |
564 protected: | |
565 FakeRTCStatsCollector( | |
566 PeerConnection* pc, | |
567 int64_t cache_lifetime) | |
568 : RTCStatsCollector(pc, cache_lifetime), | |
569 signaling_thread_(pc->session()->signaling_thread()), | |
570 worker_thread_(pc->session()->worker_thread()), | |
571 network_thread_(pc->session()->network_thread()) { | |
572 } | |
573 | |
574 void ProducePartialResultsOnSignalingThread(int64_t timestamp_us) override { | |
575 EXPECT_TRUE(signaling_thread_->IsCurrent()); | |
576 { | |
577 rtc::CritScope cs(&lock_); | |
578 EXPECT_FALSE(delivered_report_); | |
579 ++produced_on_signaling_thread_; | |
580 } | |
581 | |
582 rtc::scoped_refptr<RTCStatsReport> signaling_report = | |
583 RTCStatsReport::Create(0); | |
584 signaling_report->AddStats(std::unique_ptr<const RTCStats>( | |
585 new RTCTestStats("SignalingThreadStats", timestamp_us))); | |
586 AddPartialResults(signaling_report); | |
587 } | |
588 void ProducePartialResultsOnNetworkThread(int64_t timestamp_us) override { | |
589 EXPECT_TRUE(network_thread_->IsCurrent()); | |
590 { | |
591 rtc::CritScope cs(&lock_); | |
592 EXPECT_FALSE(delivered_report_); | |
593 ++produced_on_network_thread_; | |
594 } | |
595 | |
596 rtc::scoped_refptr<RTCStatsReport> network_report = | |
597 RTCStatsReport::Create(0); | |
598 network_report->AddStats(std::unique_ptr<const RTCStats>( | |
599 new RTCTestStats("NetworkThreadStats", timestamp_us))); | |
600 AddPartialResults(network_report); | |
601 } | |
602 | |
603 private: | |
604 rtc::Thread* const signaling_thread_; | |
605 rtc::Thread* const worker_thread_; | |
606 rtc::Thread* const network_thread_; | |
607 | |
608 rtc::CriticalSection lock_; | |
609 rtc::scoped_refptr<const RTCStatsReport> delivered_report_; | |
610 int produced_on_signaling_thread_ = 0; | |
611 int produced_on_network_thread_ = 0; | |
612 }; | |
613 | |
614 class RTCStatsCollectorTest : public testing::Test { | |
615 public: | |
616 RTCStatsCollectorTest() | |
617 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()), | |
618 collector_(RTCStatsCollector::Create( | |
619 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) { | |
620 } | |
621 | |
622 rtc::scoped_refptr<const RTCStatsReport> GetStatsReport() { | |
623 rtc::scoped_refptr<RTCStatsObtainer> callback = RTCStatsObtainer::Create(); | |
624 collector_->GetStatsReport(callback); | |
625 EXPECT_TRUE_WAIT(callback->report(), kGetStatsReportTimeoutMs); | |
626 int64_t after = rtc::TimeUTCMicros(); | |
627 for (const RTCStats& stats : *callback->report()) { | |
628 EXPECT_LE(stats.timestamp_us(), after); | |
629 } | |
630 return callback->report(); | |
631 } | |
632 | |
633 void ExpectReportContainsCertificateInfo( | |
634 const rtc::scoped_refptr<const RTCStatsReport>& report, | |
635 const CertificateInfo& certinfo) { | |
636 for (size_t i = 0; i < certinfo.fingerprints.size(); ++i) { | |
637 RTCCertificateStats expected_certificate_stats( | |
638 "RTCCertificate_" + certinfo.fingerprints[i], | |
639 report->timestamp_us()); | |
640 expected_certificate_stats.fingerprint = certinfo.fingerprints[i]; | |
641 expected_certificate_stats.fingerprint_algorithm = "sha-1"; | |
642 expected_certificate_stats.base64_certificate = certinfo.pems[i]; | |
643 if (i + 1 < certinfo.fingerprints.size()) { | |
644 expected_certificate_stats.issuer_certificate_id = | |
645 "RTCCertificate_" + certinfo.fingerprints[i + 1]; | |
646 } | |
647 ASSERT_TRUE(report->Get(expected_certificate_stats.id())); | |
648 EXPECT_EQ(expected_certificate_stats, | |
649 report->Get(expected_certificate_stats.id())->cast_to< | |
650 RTCCertificateStats>()); | |
651 } | |
652 } | |
653 | |
654 protected: | |
655 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_; | |
656 rtc::scoped_refptr<RTCStatsCollector> collector_; | |
657 }; | |
658 | |
659 TEST_F(RTCStatsCollectorTest, SingleCallback) { | |
660 rtc::scoped_refptr<const RTCStatsReport> result; | |
661 collector_->GetStatsReport(RTCStatsObtainer::Create(&result)); | |
662 EXPECT_TRUE_WAIT(result, kGetStatsReportTimeoutMs); | |
663 } | |
664 | |
665 TEST_F(RTCStatsCollectorTest, MultipleCallbacks) { | |
666 rtc::scoped_refptr<const RTCStatsReport> a; | |
667 rtc::scoped_refptr<const RTCStatsReport> b; | |
668 rtc::scoped_refptr<const RTCStatsReport> c; | |
669 collector_->GetStatsReport(RTCStatsObtainer::Create(&a)); | |
670 collector_->GetStatsReport(RTCStatsObtainer::Create(&b)); | |
671 collector_->GetStatsReport(RTCStatsObtainer::Create(&c)); | |
672 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs); | |
673 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs); | |
674 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs); | |
675 EXPECT_EQ(a.get(), b.get()); | |
676 EXPECT_EQ(b.get(), c.get()); | |
677 } | |
678 | |
679 TEST_F(RTCStatsCollectorTest, CachedStatsReports) { | |
680 // Caching should ensure |a| and |b| are the same report. | |
681 rtc::scoped_refptr<const RTCStatsReport> a = GetStatsReport(); | |
682 rtc::scoped_refptr<const RTCStatsReport> b = GetStatsReport(); | |
683 EXPECT_EQ(a.get(), b.get()); | |
684 // Invalidate cache by clearing it. | |
685 collector_->ClearCachedStatsReport(); | |
686 rtc::scoped_refptr<const RTCStatsReport> c = GetStatsReport(); | |
687 EXPECT_NE(b.get(), c.get()); | |
688 // Invalidate cache by advancing time. | |
689 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51)); | |
690 rtc::scoped_refptr<const RTCStatsReport> d = GetStatsReport(); | |
691 EXPECT_TRUE(d); | |
692 EXPECT_NE(c.get(), d.get()); | |
693 } | |
694 | |
695 TEST_F(RTCStatsCollectorTest, MultipleCallbacksWithInvalidatedCacheInBetween) { | |
696 rtc::scoped_refptr<const RTCStatsReport> a; | |
697 rtc::scoped_refptr<const RTCStatsReport> b; | |
698 rtc::scoped_refptr<const RTCStatsReport> c; | |
699 collector_->GetStatsReport(RTCStatsObtainer::Create(&a)); | |
700 collector_->GetStatsReport(RTCStatsObtainer::Create(&b)); | |
701 // Cache is invalidated after 50 ms. | |
702 test_->fake_clock().AdvanceTime(rtc::TimeDelta::FromMilliseconds(51)); | |
703 collector_->GetStatsReport(RTCStatsObtainer::Create(&c)); | |
704 EXPECT_TRUE_WAIT(a, kGetStatsReportTimeoutMs); | |
705 EXPECT_TRUE_WAIT(b, kGetStatsReportTimeoutMs); | |
706 EXPECT_TRUE_WAIT(c, kGetStatsReportTimeoutMs); | |
707 EXPECT_EQ(a.get(), b.get()); | |
708 // The act of doing |AdvanceTime| processes all messages. If this was not the | |
709 // case we might not require |c| to be fresher than |b|. | |
710 EXPECT_NE(c.get(), b.get()); | |
711 } | |
712 | |
713 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsSingle) { | |
714 std::unique_ptr<CertificateInfo> local_certinfo = | |
715 CreateFakeCertificateAndInfoFromDers( | |
716 std::vector<std::string>({ "(local) single certificate" })); | |
717 std::unique_ptr<CertificateInfo> remote_certinfo = | |
718 CreateFakeCertificateAndInfoFromDers( | |
719 std::vector<std::string>({ "(remote) single certificate" })); | |
720 | |
721 // Mock the session to return the local and remote certificates. | |
722 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
723 [this](const ChannelNamePairs&) { | |
724 std::unique_ptr<SessionStats> stats(new SessionStats()); | |
725 stats->transport_stats["transport"].transport_name = "transport"; | |
726 return stats; | |
727 })); | |
728 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly( | |
729 Invoke([this, &local_certinfo](const std::string& transport_name, | |
730 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
731 if (transport_name == "transport") { | |
732 *certificate = local_certinfo->certificate; | |
733 return true; | |
734 } | |
735 return false; | |
736 })); | |
737 EXPECT_CALL(test_->session(), | |
738 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke( | |
739 [this, &remote_certinfo](const std::string& transport_name) { | |
740 if (transport_name == "transport") | |
741 return remote_certinfo->certificate->ssl_certificate().GetReference(); | |
742 return static_cast<rtc::SSLCertificate*>(nullptr); | |
743 })); | |
744 | |
745 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
746 ExpectReportContainsCertificateInfo(report, *local_certinfo); | |
747 ExpectReportContainsCertificateInfo(report, *remote_certinfo); | |
748 } | |
749 | |
750 TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) { | |
751 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); | |
752 cricket::VoiceChannel voice_channel( | |
753 test_->worker_thread(), test_->network_thread(), | |
754 test_->signaling_thread(), test_->media_engine(), voice_media_channel, | |
755 "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
756 | |
757 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); | |
758 cricket::VideoChannel video_channel( | |
759 test_->worker_thread(), test_->network_thread(), | |
760 test_->signaling_thread(), video_media_channel, "VideoContentName", | |
761 kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
762 | |
763 // Audio | |
764 cricket::VoiceMediaInfo voice_media_info; | |
765 | |
766 RtpCodecParameters inbound_audio_codec; | |
767 inbound_audio_codec.payload_type = 1; | |
768 inbound_audio_codec.mime_type = "opus"; | |
769 inbound_audio_codec.clock_rate = 1337; | |
770 voice_media_info.receive_codecs.insert( | |
771 std::make_pair(inbound_audio_codec.payload_type, inbound_audio_codec)); | |
772 | |
773 RtpCodecParameters outbound_audio_codec; | |
774 outbound_audio_codec.payload_type = 2; | |
775 outbound_audio_codec.mime_type = "isac"; | |
776 outbound_audio_codec.clock_rate = 1338; | |
777 voice_media_info.send_codecs.insert( | |
778 std::make_pair(outbound_audio_codec.payload_type, outbound_audio_codec)); | |
779 | |
780 EXPECT_CALL(*voice_media_channel, GetStats(_)) | |
781 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true))); | |
782 | |
783 // Video | |
784 cricket::VideoMediaInfo video_media_info; | |
785 | |
786 RtpCodecParameters inbound_video_codec; | |
787 inbound_video_codec.payload_type = 3; | |
788 inbound_video_codec.mime_type = "H264"; | |
789 inbound_video_codec.clock_rate = 1339; | |
790 video_media_info.receive_codecs.insert( | |
791 std::make_pair(inbound_video_codec.payload_type, inbound_video_codec)); | |
792 | |
793 RtpCodecParameters outbound_video_codec; | |
794 outbound_video_codec.payload_type = 4; | |
795 outbound_video_codec.mime_type = "VP8"; | |
796 outbound_video_codec.clock_rate = 1340; | |
797 video_media_info.send_codecs.insert( | |
798 std::make_pair(outbound_video_codec.payload_type, outbound_video_codec)); | |
799 | |
800 EXPECT_CALL(*video_media_channel, GetStats(_)) | |
801 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true))); | |
802 | |
803 SessionStats session_stats; | |
804 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName"; | |
805 session_stats.proxy_to_transport["VideoContentName"] = "TransportName"; | |
806 session_stats.transport_stats["TransportName"].transport_name = | |
807 "TransportName"; | |
808 | |
809 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
810 [&session_stats](const ChannelNamePairs&) { | |
811 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
812 })); | |
813 EXPECT_CALL(test_->session(), voice_channel()) | |
814 .WillRepeatedly(Return(&voice_channel)); | |
815 EXPECT_CALL(test_->session(), video_channel()) | |
816 .WillRepeatedly(Return(&video_channel)); | |
817 | |
818 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
819 | |
820 RTCCodecStats expected_inbound_audio_codec( | |
821 "RTCCodec_InboundAudio_1", report->timestamp_us()); | |
822 expected_inbound_audio_codec.payload_type = 1; | |
823 expected_inbound_audio_codec.codec = "audio/opus"; | |
824 expected_inbound_audio_codec.clock_rate = 1337; | |
825 | |
826 RTCCodecStats expected_outbound_audio_codec( | |
827 "RTCCodec_OutboundAudio_2", report->timestamp_us()); | |
828 expected_outbound_audio_codec.payload_type = 2; | |
829 expected_outbound_audio_codec.codec = "audio/isac"; | |
830 expected_outbound_audio_codec.clock_rate = 1338; | |
831 | |
832 RTCCodecStats expected_inbound_video_codec( | |
833 "RTCCodec_InboundVideo_3", report->timestamp_us()); | |
834 expected_inbound_video_codec.payload_type = 3; | |
835 expected_inbound_video_codec.codec = "video/H264"; | |
836 expected_inbound_video_codec.clock_rate = 1339; | |
837 | |
838 RTCCodecStats expected_outbound_video_codec( | |
839 "RTCCodec_OutboundVideo_4", report->timestamp_us()); | |
840 expected_outbound_video_codec.payload_type = 4; | |
841 expected_outbound_video_codec.codec = "video/VP8"; | |
842 expected_outbound_video_codec.clock_rate = 1340; | |
843 | |
844 ASSERT_TRUE(report->Get(expected_inbound_audio_codec.id())); | |
845 EXPECT_EQ(expected_inbound_audio_codec, | |
846 report->Get(expected_inbound_audio_codec.id())->cast_to< | |
847 RTCCodecStats>()); | |
848 | |
849 ASSERT_TRUE(report->Get(expected_outbound_audio_codec.id())); | |
850 EXPECT_EQ(expected_outbound_audio_codec, | |
851 report->Get(expected_outbound_audio_codec.id())->cast_to< | |
852 RTCCodecStats>()); | |
853 | |
854 ASSERT_TRUE(report->Get(expected_inbound_video_codec.id())); | |
855 EXPECT_EQ(expected_inbound_video_codec, | |
856 report->Get(expected_inbound_video_codec.id())->cast_to< | |
857 RTCCodecStats>()); | |
858 | |
859 ASSERT_TRUE(report->Get(expected_outbound_video_codec.id())); | |
860 EXPECT_EQ(expected_outbound_video_codec, | |
861 report->Get(expected_outbound_video_codec.id())->cast_to< | |
862 RTCCodecStats>()); | |
863 } | |
864 | |
865 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsMultiple) { | |
866 std::unique_ptr<CertificateInfo> audio_local_certinfo = | |
867 CreateFakeCertificateAndInfoFromDers( | |
868 std::vector<std::string>({ "(local) audio" })); | |
869 audio_local_certinfo = CreateFakeCertificateAndInfoFromDers( | |
870 audio_local_certinfo->ders); | |
871 std::unique_ptr<CertificateInfo> audio_remote_certinfo = | |
872 CreateFakeCertificateAndInfoFromDers( | |
873 std::vector<std::string>({ "(remote) audio" })); | |
874 audio_remote_certinfo = CreateFakeCertificateAndInfoFromDers( | |
875 audio_remote_certinfo->ders); | |
876 | |
877 std::unique_ptr<CertificateInfo> video_local_certinfo = | |
878 CreateFakeCertificateAndInfoFromDers( | |
879 std::vector<std::string>({ "(local) video" })); | |
880 video_local_certinfo = CreateFakeCertificateAndInfoFromDers( | |
881 video_local_certinfo->ders); | |
882 std::unique_ptr<CertificateInfo> video_remote_certinfo = | |
883 CreateFakeCertificateAndInfoFromDers( | |
884 std::vector<std::string>({ "(remote) video" })); | |
885 video_remote_certinfo = CreateFakeCertificateAndInfoFromDers( | |
886 video_remote_certinfo->ders); | |
887 | |
888 // Mock the session to return the local and remote certificates. | |
889 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
890 [this](const ChannelNamePairs&) { | |
891 std::unique_ptr<SessionStats> stats(new SessionStats()); | |
892 stats->transport_stats["audio"].transport_name = "audio"; | |
893 stats->transport_stats["video"].transport_name = "video"; | |
894 return stats; | |
895 })); | |
896 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly( | |
897 Invoke([this, &audio_local_certinfo, &video_local_certinfo]( | |
898 const std::string& transport_name, | |
899 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
900 if (transport_name == "audio") { | |
901 *certificate = audio_local_certinfo->certificate; | |
902 return true; | |
903 } | |
904 if (transport_name == "video") { | |
905 *certificate = video_local_certinfo->certificate; | |
906 return true; | |
907 } | |
908 return false; | |
909 })); | |
910 EXPECT_CALL(test_->session(), | |
911 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke( | |
912 [this, &audio_remote_certinfo, &video_remote_certinfo]( | |
913 const std::string& transport_name) { | |
914 if (transport_name == "audio") { | |
915 return audio_remote_certinfo->certificate->ssl_certificate() | |
916 .GetReference(); | |
917 } | |
918 if (transport_name == "video") { | |
919 return video_remote_certinfo->certificate->ssl_certificate() | |
920 .GetReference(); | |
921 } | |
922 return static_cast<rtc::SSLCertificate*>(nullptr); | |
923 })); | |
924 | |
925 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
926 ExpectReportContainsCertificateInfo(report, *audio_local_certinfo); | |
927 ExpectReportContainsCertificateInfo(report, *audio_remote_certinfo); | |
928 ExpectReportContainsCertificateInfo(report, *video_local_certinfo); | |
929 ExpectReportContainsCertificateInfo(report, *video_remote_certinfo); | |
930 } | |
931 | |
932 TEST_F(RTCStatsCollectorTest, CollectRTCCertificateStatsChain) { | |
933 std::vector<std::string> local_ders; | |
934 local_ders.push_back("(local) this"); | |
935 local_ders.push_back("(local) is"); | |
936 local_ders.push_back("(local) a"); | |
937 local_ders.push_back("(local) chain"); | |
938 std::unique_ptr<CertificateInfo> local_certinfo = | |
939 CreateFakeCertificateAndInfoFromDers(local_ders); | |
940 std::vector<std::string> remote_ders; | |
941 remote_ders.push_back("(remote) this"); | |
942 remote_ders.push_back("(remote) is"); | |
943 remote_ders.push_back("(remote) another"); | |
944 remote_ders.push_back("(remote) chain"); | |
945 std::unique_ptr<CertificateInfo> remote_certinfo = | |
946 CreateFakeCertificateAndInfoFromDers(remote_ders); | |
947 | |
948 // Mock the session to return the local and remote certificates. | |
949 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
950 [this](const ChannelNamePairs&) { | |
951 std::unique_ptr<SessionStats> stats(new SessionStats()); | |
952 stats->transport_stats["transport"].transport_name = "transport"; | |
953 return stats; | |
954 })); | |
955 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly( | |
956 Invoke([this, &local_certinfo](const std::string& transport_name, | |
957 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
958 if (transport_name == "transport") { | |
959 *certificate = local_certinfo->certificate; | |
960 return true; | |
961 } | |
962 return false; | |
963 })); | |
964 EXPECT_CALL(test_->session(), | |
965 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke( | |
966 [this, &remote_certinfo](const std::string& transport_name) { | |
967 if (transport_name == "transport") | |
968 return remote_certinfo->certificate->ssl_certificate().GetReference(); | |
969 return static_cast<rtc::SSLCertificate*>(nullptr); | |
970 })); | |
971 | |
972 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
973 ExpectReportContainsCertificateInfo(report, *local_certinfo); | |
974 ExpectReportContainsCertificateInfo(report, *remote_certinfo); | |
975 } | |
976 | |
977 TEST_F(RTCStatsCollectorTest, CollectRTCDataChannelStats) { | |
978 test_->data_channels().push_back( | |
979 new MockDataChannel( | |
980 0, "MockDataChannel0", DataChannelInterface::kConnecting, "udp", | |
981 1, 2, 3, 4)); | |
982 RTCDataChannelStats expected_data_channel0("RTCDataChannel_0", 0); | |
983 expected_data_channel0.label = "MockDataChannel0"; | |
984 expected_data_channel0.protocol = "udp"; | |
985 expected_data_channel0.datachannelid = 0; | |
986 expected_data_channel0.state = "connecting"; | |
987 expected_data_channel0.messages_sent = 1; | |
988 expected_data_channel0.bytes_sent = 2; | |
989 expected_data_channel0.messages_received = 3; | |
990 expected_data_channel0.bytes_received = 4; | |
991 | |
992 test_->data_channels().push_back( | |
993 new MockDataChannel( | |
994 1, "MockDataChannel1", DataChannelInterface::kOpen, "tcp", | |
995 5, 6, 7, 8)); | |
996 RTCDataChannelStats expected_data_channel1("RTCDataChannel_1", 0); | |
997 expected_data_channel1.label = "MockDataChannel1"; | |
998 expected_data_channel1.protocol = "tcp"; | |
999 expected_data_channel1.datachannelid = 1; | |
1000 expected_data_channel1.state = "open"; | |
1001 expected_data_channel1.messages_sent = 5; | |
1002 expected_data_channel1.bytes_sent = 6; | |
1003 expected_data_channel1.messages_received = 7; | |
1004 expected_data_channel1.bytes_received = 8; | |
1005 | |
1006 test_->data_channels().push_back( | |
1007 new MockDataChannel( | |
1008 2, "MockDataChannel2", DataChannelInterface::kClosing, "udp", | |
1009 9, 10, 11, 12)); | |
1010 RTCDataChannelStats expected_data_channel2("RTCDataChannel_2", 0); | |
1011 expected_data_channel2.label = "MockDataChannel2"; | |
1012 expected_data_channel2.protocol = "udp"; | |
1013 expected_data_channel2.datachannelid = 2; | |
1014 expected_data_channel2.state = "closing"; | |
1015 expected_data_channel2.messages_sent = 9; | |
1016 expected_data_channel2.bytes_sent = 10; | |
1017 expected_data_channel2.messages_received = 11; | |
1018 expected_data_channel2.bytes_received = 12; | |
1019 | |
1020 test_->data_channels().push_back( | |
1021 new MockDataChannel( | |
1022 3, "MockDataChannel3", DataChannelInterface::kClosed, "tcp", | |
1023 13, 14, 15, 16)); | |
1024 RTCDataChannelStats expected_data_channel3("RTCDataChannel_3", 0); | |
1025 expected_data_channel3.label = "MockDataChannel3"; | |
1026 expected_data_channel3.protocol = "tcp"; | |
1027 expected_data_channel3.datachannelid = 3; | |
1028 expected_data_channel3.state = "closed"; | |
1029 expected_data_channel3.messages_sent = 13; | |
1030 expected_data_channel3.bytes_sent = 14; | |
1031 expected_data_channel3.messages_received = 15; | |
1032 expected_data_channel3.bytes_received = 16; | |
1033 | |
1034 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1035 ASSERT_TRUE(report->Get(expected_data_channel0.id())); | |
1036 EXPECT_EQ(expected_data_channel0, | |
1037 report->Get(expected_data_channel0.id())->cast_to< | |
1038 RTCDataChannelStats>()); | |
1039 ASSERT_TRUE(report->Get(expected_data_channel1.id())); | |
1040 EXPECT_EQ(expected_data_channel1, | |
1041 report->Get(expected_data_channel1.id())->cast_to< | |
1042 RTCDataChannelStats>()); | |
1043 ASSERT_TRUE(report->Get(expected_data_channel2.id())); | |
1044 EXPECT_EQ(expected_data_channel2, | |
1045 report->Get(expected_data_channel2.id())->cast_to< | |
1046 RTCDataChannelStats>()); | |
1047 ASSERT_TRUE(report->Get(expected_data_channel3.id())); | |
1048 EXPECT_EQ(expected_data_channel3, | |
1049 report->Get(expected_data_channel3.id())->cast_to< | |
1050 RTCDataChannelStats>()); | |
1051 } | |
1052 | |
1053 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) { | |
1054 // Candidates in the first transport stats. | |
1055 std::unique_ptr<cricket::Candidate> a_local_host = CreateFakeCandidate( | |
1056 "1.2.3.4", 5, | |
1057 "a_local_host's protocol", | |
1058 cricket::LOCAL_PORT_TYPE, | |
1059 0); | |
1060 RTCLocalIceCandidateStats expected_a_local_host( | |
1061 "RTCIceCandidate_" + a_local_host->id(), 0); | |
1062 expected_a_local_host.transport_id = "RTCTransport_a_0"; | |
1063 expected_a_local_host.ip = "1.2.3.4"; | |
1064 expected_a_local_host.port = 5; | |
1065 expected_a_local_host.protocol = "a_local_host's protocol"; | |
1066 expected_a_local_host.candidate_type = "host"; | |
1067 expected_a_local_host.priority = 0; | |
1068 EXPECT_FALSE(*expected_a_local_host.is_remote); | |
1069 | |
1070 std::unique_ptr<cricket::Candidate> a_remote_srflx = CreateFakeCandidate( | |
1071 "6.7.8.9", 10, | |
1072 "remote_srflx's protocol", | |
1073 cricket::STUN_PORT_TYPE, | |
1074 1); | |
1075 RTCRemoteIceCandidateStats expected_a_remote_srflx( | |
1076 "RTCIceCandidate_" + a_remote_srflx->id(), 0); | |
1077 expected_a_remote_srflx.transport_id = "RTCTransport_a_0"; | |
1078 expected_a_remote_srflx.ip = "6.7.8.9"; | |
1079 expected_a_remote_srflx.port = 10; | |
1080 expected_a_remote_srflx.protocol = "remote_srflx's protocol"; | |
1081 expected_a_remote_srflx.candidate_type = "srflx"; | |
1082 expected_a_remote_srflx.priority = 1; | |
1083 expected_a_remote_srflx.deleted = false; | |
1084 EXPECT_TRUE(*expected_a_remote_srflx.is_remote); | |
1085 | |
1086 std::unique_ptr<cricket::Candidate> a_local_prflx = CreateFakeCandidate( | |
1087 "11.12.13.14", 15, | |
1088 "a_local_prflx's protocol", | |
1089 cricket::PRFLX_PORT_TYPE, | |
1090 2); | |
1091 RTCLocalIceCandidateStats expected_a_local_prflx( | |
1092 "RTCIceCandidate_" + a_local_prflx->id(), 0); | |
1093 expected_a_local_prflx.transport_id = "RTCTransport_a_0"; | |
1094 expected_a_local_prflx.ip = "11.12.13.14"; | |
1095 expected_a_local_prflx.port = 15; | |
1096 expected_a_local_prflx.protocol = "a_local_prflx's protocol"; | |
1097 expected_a_local_prflx.candidate_type = "prflx"; | |
1098 expected_a_local_prflx.priority = 2; | |
1099 expected_a_local_prflx.deleted = false; | |
1100 EXPECT_FALSE(*expected_a_local_prflx.is_remote); | |
1101 | |
1102 std::unique_ptr<cricket::Candidate> a_remote_relay = CreateFakeCandidate( | |
1103 "16.17.18.19", 20, | |
1104 "a_remote_relay's protocol", | |
1105 cricket::RELAY_PORT_TYPE, | |
1106 3); | |
1107 RTCRemoteIceCandidateStats expected_a_remote_relay( | |
1108 "RTCIceCandidate_" + a_remote_relay->id(), 0); | |
1109 expected_a_remote_relay.transport_id = "RTCTransport_a_0"; | |
1110 expected_a_remote_relay.ip = "16.17.18.19"; | |
1111 expected_a_remote_relay.port = 20; | |
1112 expected_a_remote_relay.protocol = "a_remote_relay's protocol"; | |
1113 expected_a_remote_relay.candidate_type = "relay"; | |
1114 expected_a_remote_relay.priority = 3; | |
1115 expected_a_remote_relay.deleted = false; | |
1116 EXPECT_TRUE(*expected_a_remote_relay.is_remote); | |
1117 | |
1118 // Candidates in the second transport stats. | |
1119 std::unique_ptr<cricket::Candidate> b_local = CreateFakeCandidate( | |
1120 "42.42.42.42", 42, | |
1121 "b_local's protocol", | |
1122 cricket::LOCAL_PORT_TYPE, | |
1123 42); | |
1124 RTCLocalIceCandidateStats expected_b_local( | |
1125 "RTCIceCandidate_" + b_local->id(), 0); | |
1126 expected_b_local.transport_id = "RTCTransport_b_0"; | |
1127 expected_b_local.ip = "42.42.42.42"; | |
1128 expected_b_local.port = 42; | |
1129 expected_b_local.protocol = "b_local's protocol"; | |
1130 expected_b_local.candidate_type = "host"; | |
1131 expected_b_local.priority = 42; | |
1132 expected_b_local.deleted = false; | |
1133 EXPECT_FALSE(*expected_b_local.is_remote); | |
1134 | |
1135 std::unique_ptr<cricket::Candidate> b_remote = CreateFakeCandidate( | |
1136 "42.42.42.42", 42, | |
1137 "b_remote's protocol", | |
1138 cricket::LOCAL_PORT_TYPE, | |
1139 42); | |
1140 RTCRemoteIceCandidateStats expected_b_remote( | |
1141 "RTCIceCandidate_" + b_remote->id(), 0); | |
1142 expected_b_remote.transport_id = "RTCTransport_b_0"; | |
1143 expected_b_remote.ip = "42.42.42.42"; | |
1144 expected_b_remote.port = 42; | |
1145 expected_b_remote.protocol = "b_remote's protocol"; | |
1146 expected_b_remote.candidate_type = "host"; | |
1147 expected_b_remote.priority = 42; | |
1148 expected_b_remote.deleted = false; | |
1149 EXPECT_TRUE(*expected_b_remote.is_remote); | |
1150 | |
1151 SessionStats session_stats; | |
1152 | |
1153 cricket::TransportChannelStats a_transport_channel_stats; | |
1154 a_transport_channel_stats.connection_infos.push_back( | |
1155 cricket::ConnectionInfo()); | |
1156 a_transport_channel_stats.connection_infos[0].local_candidate = | |
1157 *a_local_host.get(); | |
1158 a_transport_channel_stats.connection_infos[0].remote_candidate = | |
1159 *a_remote_srflx.get(); | |
1160 a_transport_channel_stats.connection_infos.push_back( | |
1161 cricket::ConnectionInfo()); | |
1162 a_transport_channel_stats.connection_infos[1].local_candidate = | |
1163 *a_local_prflx.get(); | |
1164 a_transport_channel_stats.connection_infos[1].remote_candidate = | |
1165 *a_remote_relay.get(); | |
1166 session_stats.transport_stats["a"].transport_name = "a"; | |
1167 session_stats.transport_stats["a"].channel_stats.push_back( | |
1168 a_transport_channel_stats); | |
1169 | |
1170 cricket::TransportChannelStats b_transport_channel_stats; | |
1171 b_transport_channel_stats.connection_infos.push_back( | |
1172 cricket::ConnectionInfo()); | |
1173 b_transport_channel_stats.connection_infos[0].local_candidate = | |
1174 *b_local.get(); | |
1175 b_transport_channel_stats.connection_infos[0].remote_candidate = | |
1176 *b_remote.get(); | |
1177 session_stats.transport_stats["b"].transport_name = "b"; | |
1178 session_stats.transport_stats["b"].channel_stats.push_back( | |
1179 b_transport_channel_stats); | |
1180 | |
1181 // Mock the session to return the desired candidates. | |
1182 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1183 [&session_stats](const ChannelNamePairs&) { | |
1184 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1185 })); | |
1186 | |
1187 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1188 | |
1189 ASSERT_TRUE(report->Get(expected_a_local_host.id())); | |
1190 EXPECT_EQ(expected_a_local_host, | |
1191 report->Get(expected_a_local_host.id())->cast_to< | |
1192 RTCLocalIceCandidateStats>()); | |
1193 ASSERT_TRUE(report->Get(expected_a_remote_srflx.id())); | |
1194 EXPECT_EQ(expected_a_remote_srflx, | |
1195 report->Get(expected_a_remote_srflx.id())->cast_to< | |
1196 RTCRemoteIceCandidateStats>()); | |
1197 ASSERT_TRUE(report->Get(expected_a_local_prflx.id())); | |
1198 EXPECT_EQ(expected_a_local_prflx, | |
1199 report->Get(expected_a_local_prflx.id())->cast_to< | |
1200 RTCLocalIceCandidateStats>()); | |
1201 ASSERT_TRUE(report->Get(expected_a_remote_relay.id())); | |
1202 EXPECT_EQ(expected_a_remote_relay, | |
1203 report->Get(expected_a_remote_relay.id())->cast_to< | |
1204 RTCRemoteIceCandidateStats>()); | |
1205 ASSERT_TRUE(report->Get(expected_b_local.id())); | |
1206 EXPECT_EQ(expected_b_local, | |
1207 report->Get(expected_b_local.id())->cast_to< | |
1208 RTCLocalIceCandidateStats>()); | |
1209 ASSERT_TRUE(report->Get(expected_b_remote.id())); | |
1210 EXPECT_EQ(expected_b_remote, | |
1211 report->Get(expected_b_remote.id())->cast_to< | |
1212 RTCRemoteIceCandidateStats>()); | |
1213 EXPECT_TRUE(report->Get("RTCTransport_a_0")); | |
1214 EXPECT_TRUE(report->Get("RTCTransport_b_0")); | |
1215 } | |
1216 | |
1217 TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) { | |
1218 std::unique_ptr<cricket::Candidate> local_candidate = CreateFakeCandidate( | |
1219 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42); | |
1220 std::unique_ptr<cricket::Candidate> remote_candidate = CreateFakeCandidate( | |
1221 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42); | |
1222 | |
1223 SessionStats session_stats; | |
1224 | |
1225 cricket::ConnectionInfo connection_info; | |
1226 connection_info.local_candidate = *local_candidate.get(); | |
1227 connection_info.remote_candidate = *remote_candidate.get(); | |
1228 connection_info.writable = true; | |
1229 connection_info.sent_total_bytes = 42; | |
1230 connection_info.recv_total_bytes = 1234; | |
1231 connection_info.rtt = 1337; | |
1232 connection_info.recv_ping_requests = 2020; | |
1233 connection_info.sent_ping_requests_total = 2020; | |
1234 connection_info.sent_ping_requests_before_first_response = 2000; | |
1235 connection_info.recv_ping_responses = 4321; | |
1236 connection_info.sent_ping_responses = 1000; | |
1237 connection_info.state = cricket::IceCandidatePairState::IN_PROGRESS; | |
1238 connection_info.priority = 5555; | |
1239 | |
1240 cricket::TransportChannelStats transport_channel_stats; | |
1241 transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
1242 transport_channel_stats.connection_infos.push_back(connection_info); | |
1243 session_stats.transport_stats["transport"].transport_name = "transport"; | |
1244 session_stats.transport_stats["transport"].channel_stats.push_back( | |
1245 transport_channel_stats); | |
1246 | |
1247 // Mock the session to return the desired candidates. | |
1248 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1249 [&session_stats](const ChannelNamePairs&) { | |
1250 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1251 })); | |
1252 | |
1253 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1254 | |
1255 RTCIceCandidatePairStats expected_pair("RTCIceCandidatePair_" + | |
1256 local_candidate->id() + "_" + | |
1257 remote_candidate->id(), | |
1258 report->timestamp_us()); | |
1259 expected_pair.transport_id = | |
1260 "RTCTransport_transport_" + | |
1261 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
1262 expected_pair.local_candidate_id = "RTCIceCandidate_" + local_candidate->id(); | |
1263 expected_pair.remote_candidate_id = | |
1264 "RTCIceCandidate_" + remote_candidate->id(); | |
1265 expected_pair.state = RTCStatsIceCandidatePairState::kInProgress; | |
1266 expected_pair.priority = 5555; | |
1267 expected_pair.writable = true; | |
1268 expected_pair.bytes_sent = 42; | |
1269 expected_pair.bytes_received = 1234; | |
1270 expected_pair.current_round_trip_time = 1.337; | |
1271 expected_pair.requests_received = 2020; | |
1272 expected_pair.requests_sent = 2000; | |
1273 expected_pair.responses_received = 4321; | |
1274 expected_pair.responses_sent = 1000; | |
1275 expected_pair.consent_requests_sent = (2020 - 2000); | |
1276 | |
1277 ASSERT_TRUE(report->Get(expected_pair.id())); | |
1278 EXPECT_EQ( | |
1279 expected_pair, | |
1280 report->Get(expected_pair.id())->cast_to<RTCIceCandidatePairStats>()); | |
1281 EXPECT_TRUE(report->Get(*expected_pair.transport_id)); | |
1282 | |
1283 RTCLocalIceCandidateStats expected_local_candidate( | |
1284 *expected_pair.local_candidate_id, report->timestamp_us()); | |
1285 expected_local_candidate.transport_id = *expected_pair.transport_id; | |
1286 expected_local_candidate.ip = "42.42.42.42"; | |
1287 expected_local_candidate.port = 42; | |
1288 expected_local_candidate.protocol = "protocol"; | |
1289 expected_local_candidate.candidate_type = "host"; | |
1290 expected_local_candidate.priority = 42; | |
1291 expected_local_candidate.deleted = false; | |
1292 EXPECT_FALSE(*expected_local_candidate.is_remote); | |
1293 ASSERT_TRUE(report->Get(expected_local_candidate.id())); | |
1294 EXPECT_EQ(expected_local_candidate, | |
1295 report->Get(expected_local_candidate.id())->cast_to< | |
1296 RTCLocalIceCandidateStats>()); | |
1297 | |
1298 RTCRemoteIceCandidateStats expected_remote_candidate( | |
1299 *expected_pair.remote_candidate_id, report->timestamp_us()); | |
1300 expected_remote_candidate.transport_id = *expected_pair.transport_id; | |
1301 expected_remote_candidate.ip = "42.42.42.42"; | |
1302 expected_remote_candidate.port = 42; | |
1303 expected_remote_candidate.protocol = "protocol"; | |
1304 expected_remote_candidate.candidate_type = "host"; | |
1305 expected_remote_candidate.priority = 42; | |
1306 expected_remote_candidate.deleted = false; | |
1307 EXPECT_TRUE(*expected_remote_candidate.is_remote); | |
1308 ASSERT_TRUE(report->Get(expected_remote_candidate.id())); | |
1309 EXPECT_EQ(expected_remote_candidate, | |
1310 report->Get(expected_remote_candidate.id())->cast_to< | |
1311 RTCRemoteIceCandidateStats>()); | |
1312 } | |
1313 | |
1314 TEST_F(RTCStatsCollectorTest, CollectRTCPeerConnectionStats) { | |
1315 { | |
1316 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1317 RTCPeerConnectionStats expected("RTCPeerConnection", | |
1318 report->timestamp_us()); | |
1319 expected.data_channels_opened = 0; | |
1320 expected.data_channels_closed = 0; | |
1321 ASSERT_TRUE(report->Get("RTCPeerConnection")); | |
1322 EXPECT_EQ(expected, | |
1323 report->Get("RTCPeerConnection")->cast_to< | |
1324 RTCPeerConnectionStats>()); | |
1325 } | |
1326 | |
1327 rtc::scoped_refptr<DataChannel> dummy_channel_a = DataChannel::Create( | |
1328 nullptr, cricket::DCT_NONE, "DummyChannelA", InternalDataChannelInit()); | |
1329 test_->pc().SignalDataChannelCreated(dummy_channel_a.get()); | |
1330 rtc::scoped_refptr<DataChannel> dummy_channel_b = DataChannel::Create( | |
1331 nullptr, cricket::DCT_NONE, "DummyChannelB", InternalDataChannelInit()); | |
1332 test_->pc().SignalDataChannelCreated(dummy_channel_b.get()); | |
1333 | |
1334 dummy_channel_a->SignalOpened(dummy_channel_a.get()); | |
1335 // Closing a channel that is not opened should not affect the counts. | |
1336 dummy_channel_b->SignalClosed(dummy_channel_b.get()); | |
1337 | |
1338 { | |
1339 collector_->ClearCachedStatsReport(); | |
1340 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1341 RTCPeerConnectionStats expected("RTCPeerConnection", | |
1342 report->timestamp_us()); | |
1343 expected.data_channels_opened = 1; | |
1344 expected.data_channels_closed = 0; | |
1345 ASSERT_TRUE(report->Get("RTCPeerConnection")); | |
1346 EXPECT_EQ(expected, | |
1347 report->Get("RTCPeerConnection")->cast_to< | |
1348 RTCPeerConnectionStats>()); | |
1349 } | |
1350 | |
1351 dummy_channel_b->SignalOpened(dummy_channel_b.get()); | |
1352 dummy_channel_b->SignalClosed(dummy_channel_b.get()); | |
1353 | |
1354 { | |
1355 collector_->ClearCachedStatsReport(); | |
1356 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1357 RTCPeerConnectionStats expected("RTCPeerConnection", | |
1358 report->timestamp_us()); | |
1359 expected.data_channels_opened = 2; | |
1360 expected.data_channels_closed = 1; | |
1361 ASSERT_TRUE(report->Get("RTCPeerConnection")); | |
1362 EXPECT_EQ(expected, | |
1363 report->Get("RTCPeerConnection")->cast_to< | |
1364 RTCPeerConnectionStats>()); | |
1365 } | |
1366 } | |
1367 | |
1368 TEST_F(RTCStatsCollectorTest, | |
1369 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Audio) { | |
1370 rtc::scoped_refptr<StreamCollection> local_streams = | |
1371 StreamCollection::Create(); | |
1372 rtc::scoped_refptr<StreamCollection> remote_streams = | |
1373 StreamCollection::Create(); | |
1374 EXPECT_CALL(test_->pc(), local_streams()) | |
1375 .WillRepeatedly(Return(local_streams)); | |
1376 EXPECT_CALL(test_->pc(), remote_streams()) | |
1377 .WillRepeatedly(Return(remote_streams)); | |
1378 | |
1379 rtc::scoped_refptr<MediaStream> local_stream = | |
1380 MediaStream::Create("LocalStreamLabel"); | |
1381 local_streams->AddStream(local_stream); | |
1382 rtc::scoped_refptr<MediaStream> remote_stream = | |
1383 MediaStream::Create("RemoteStreamLabel"); | |
1384 remote_streams->AddStream(remote_stream); | |
1385 | |
1386 // Local audio track | |
1387 rtc::scoped_refptr<MediaStreamTrackInterface> local_audio_track = | |
1388 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", | |
1389 MediaStreamTrackInterface::kEnded); | |
1390 local_stream->AddTrack(static_cast<AudioTrackInterface*>( | |
1391 local_audio_track.get())); | |
1392 | |
1393 cricket::VoiceSenderInfo voice_sender_info_ssrc1; | |
1394 voice_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo()); | |
1395 voice_sender_info_ssrc1.local_stats[0].ssrc = 1; | |
1396 voice_sender_info_ssrc1.audio_level = 32767; | |
1397 voice_sender_info_ssrc1.echo_return_loss = 42; | |
1398 voice_sender_info_ssrc1.echo_return_loss_enhancement = 52; | |
1399 | |
1400 // Uses default values, the corresponding stats object should contain | |
1401 // undefined members. | |
1402 cricket::VoiceSenderInfo voice_sender_info_ssrc2; | |
1403 voice_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); | |
1404 voice_sender_info_ssrc2.local_stats[0].ssrc = 2; | |
1405 voice_sender_info_ssrc2.audio_level = 0; | |
1406 voice_sender_info_ssrc2.echo_return_loss = -100; | |
1407 voice_sender_info_ssrc2.echo_return_loss_enhancement = -100; | |
1408 | |
1409 // Remote audio track | |
1410 rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track = | |
1411 CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", | |
1412 MediaStreamTrackInterface::kLive); | |
1413 remote_stream->AddTrack(static_cast<AudioTrackInterface*>( | |
1414 remote_audio_track.get())); | |
1415 | |
1416 cricket::VoiceReceiverInfo voice_receiver_info; | |
1417 voice_receiver_info.local_stats.push_back(cricket::SsrcReceiverInfo()); | |
1418 voice_receiver_info.local_stats[0].ssrc = 3; | |
1419 voice_receiver_info.audio_level = 16383; | |
1420 | |
1421 test_->CreateMockRtpSendersReceiversAndChannels( | |
1422 { std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1), | |
1423 std::make_pair(local_audio_track.get(), voice_sender_info_ssrc2) }, | |
1424 { std::make_pair(remote_audio_track.get(), voice_receiver_info) }, | |
1425 {}, {}); | |
1426 | |
1427 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1428 | |
1429 RTCMediaStreamStats expected_local_stream( | |
1430 "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); | |
1431 expected_local_stream.stream_identifier = local_stream->label(); | |
1432 expected_local_stream.track_ids = std::vector<std::string>( | |
1433 { "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", | |
1434 "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2" }); | |
1435 ASSERT_TRUE(report->Get(expected_local_stream.id())); | |
1436 EXPECT_EQ(expected_local_stream, | |
1437 report->Get(expected_local_stream.id())->cast_to< | |
1438 RTCMediaStreamStats>()); | |
1439 | |
1440 RTCMediaStreamStats expected_remote_stream( | |
1441 "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); | |
1442 expected_remote_stream.stream_identifier = remote_stream->label(); | |
1443 expected_remote_stream.track_ids = std::vector<std::string>({ | |
1444 "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3" }); | |
1445 ASSERT_TRUE(report->Get(expected_remote_stream.id())); | |
1446 EXPECT_EQ(expected_remote_stream, | |
1447 report->Get(expected_remote_stream.id())->cast_to< | |
1448 RTCMediaStreamStats>()); | |
1449 | |
1450 RTCMediaStreamTrackStats expected_local_audio_track_ssrc1( | |
1451 "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1", | |
1452 report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); | |
1453 expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id(); | |
1454 expected_local_audio_track_ssrc1.remote_source = false; | |
1455 expected_local_audio_track_ssrc1.ended = true; | |
1456 expected_local_audio_track_ssrc1.detached = false; | |
1457 expected_local_audio_track_ssrc1.audio_level = 1.0; | |
1458 expected_local_audio_track_ssrc1.echo_return_loss = 42.0; | |
1459 expected_local_audio_track_ssrc1.echo_return_loss_enhancement = 52.0; | |
1460 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc1.id())); | |
1461 EXPECT_EQ(expected_local_audio_track_ssrc1, | |
1462 report->Get(expected_local_audio_track_ssrc1.id())->cast_to< | |
1463 RTCMediaStreamTrackStats>()); | |
1464 | |
1465 RTCMediaStreamTrackStats expected_local_audio_track_ssrc2( | |
1466 "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2", | |
1467 report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); | |
1468 expected_local_audio_track_ssrc2.track_identifier = local_audio_track->id(); | |
1469 expected_local_audio_track_ssrc2.remote_source = false; | |
1470 expected_local_audio_track_ssrc2.ended = true; | |
1471 expected_local_audio_track_ssrc2.detached = false; | |
1472 expected_local_audio_track_ssrc2.audio_level = 0.0; | |
1473 // Should be undefined: |expected_local_audio_track_ssrc2.echo_return_loss| | |
1474 // and |expected_local_audio_track_ssrc2.echo_return_loss_enhancement|. | |
1475 ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc2.id())); | |
1476 EXPECT_EQ(expected_local_audio_track_ssrc2, | |
1477 report->Get(expected_local_audio_track_ssrc2.id())->cast_to< | |
1478 RTCMediaStreamTrackStats>()); | |
1479 | |
1480 RTCMediaStreamTrackStats expected_remote_audio_track( | |
1481 "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3", | |
1482 report->timestamp_us(), RTCMediaStreamTrackKind::kAudio); | |
1483 expected_remote_audio_track.track_identifier = remote_audio_track->id(); | |
1484 expected_remote_audio_track.remote_source = true; | |
1485 expected_remote_audio_track.ended = false; | |
1486 expected_remote_audio_track.detached = false; | |
1487 expected_remote_audio_track.audio_level = 16383.0 / 32767.0; | |
1488 ASSERT_TRUE(report->Get(expected_remote_audio_track.id())); | |
1489 EXPECT_EQ(expected_remote_audio_track, | |
1490 report->Get(expected_remote_audio_track.id())->cast_to< | |
1491 RTCMediaStreamTrackStats>()); | |
1492 } | |
1493 | |
1494 TEST_F(RTCStatsCollectorTest, | |
1495 CollectRTCMediaStreamStatsAndRTCMediaStreamTrackStats_Video) { | |
1496 rtc::scoped_refptr<StreamCollection> local_streams = | |
1497 StreamCollection::Create(); | |
1498 rtc::scoped_refptr<StreamCollection> remote_streams = | |
1499 StreamCollection::Create(); | |
1500 EXPECT_CALL(test_->pc(), local_streams()) | |
1501 .WillRepeatedly(Return(local_streams)); | |
1502 EXPECT_CALL(test_->pc(), remote_streams()) | |
1503 .WillRepeatedly(Return(remote_streams)); | |
1504 | |
1505 rtc::scoped_refptr<MediaStream> local_stream = | |
1506 MediaStream::Create("LocalStreamLabel"); | |
1507 local_streams->AddStream(local_stream); | |
1508 rtc::scoped_refptr<MediaStream> remote_stream = | |
1509 MediaStream::Create("RemoteStreamLabel"); | |
1510 remote_streams->AddStream(remote_stream); | |
1511 | |
1512 // Local video track | |
1513 rtc::scoped_refptr<MediaStreamTrackInterface> local_video_track = | |
1514 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", | |
1515 MediaStreamTrackInterface::kLive); | |
1516 local_stream->AddTrack(static_cast<VideoTrackInterface*>( | |
1517 local_video_track.get())); | |
1518 | |
1519 cricket::VideoSenderInfo video_sender_info_ssrc1; | |
1520 video_sender_info_ssrc1.local_stats.push_back(cricket::SsrcSenderInfo()); | |
1521 video_sender_info_ssrc1.local_stats[0].ssrc = 1; | |
1522 video_sender_info_ssrc1.send_frame_width = 1234; | |
1523 video_sender_info_ssrc1.send_frame_height = 4321; | |
1524 video_sender_info_ssrc1.frames_encoded = 11; | |
1525 | |
1526 cricket::VideoSenderInfo video_sender_info_ssrc2; | |
1527 video_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo()); | |
1528 video_sender_info_ssrc2.local_stats[0].ssrc = 2; | |
1529 video_sender_info_ssrc2.send_frame_width = 4321; | |
1530 video_sender_info_ssrc2.send_frame_height = 1234; | |
1531 video_sender_info_ssrc2.frames_encoded = 22; | |
1532 | |
1533 // Remote video track with values | |
1534 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 = | |
1535 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3", | |
1536 MediaStreamTrackInterface::kEnded); | |
1537 remote_stream->AddTrack(static_cast<VideoTrackInterface*>( | |
1538 remote_video_track_ssrc3.get())); | |
1539 | |
1540 cricket::VideoReceiverInfo video_receiver_info_ssrc3; | |
1541 video_receiver_info_ssrc3.local_stats.push_back(cricket::SsrcReceiverInfo()); | |
1542 video_receiver_info_ssrc3.local_stats[0].ssrc = 3; | |
1543 video_receiver_info_ssrc3.frame_width = 6789; | |
1544 video_receiver_info_ssrc3.frame_height = 9876; | |
1545 video_receiver_info_ssrc3.frames_received = 2468; | |
1546 video_receiver_info_ssrc3.frames_decoded = 1234; | |
1547 | |
1548 // Remote video track with undefined (default) values | |
1549 rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc4 = | |
1550 CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID4", | |
1551 MediaStreamTrackInterface::kLive); | |
1552 remote_stream->AddTrack(static_cast<VideoTrackInterface*>( | |
1553 remote_video_track_ssrc4.get())); | |
1554 | |
1555 cricket::VideoReceiverInfo video_receiver_info_ssrc4; | |
1556 video_receiver_info_ssrc4.local_stats.push_back(cricket::SsrcReceiverInfo()); | |
1557 video_receiver_info_ssrc4.local_stats[0].ssrc = 4; | |
1558 video_receiver_info_ssrc4.frame_width = 0; | |
1559 video_receiver_info_ssrc4.frame_height = 0; | |
1560 video_receiver_info_ssrc4.frames_received = 0; | |
1561 video_receiver_info_ssrc4.frames_decoded = 0; | |
1562 | |
1563 test_->CreateMockRtpSendersReceiversAndChannels( | |
1564 {}, {}, | |
1565 { std::make_pair(local_video_track.get(), video_sender_info_ssrc1), | |
1566 std::make_pair(local_video_track.get(), video_sender_info_ssrc2) }, | |
1567 { std::make_pair(remote_video_track_ssrc3.get(), | |
1568 video_receiver_info_ssrc3), | |
1569 std::make_pair(remote_video_track_ssrc4.get(), | |
1570 video_receiver_info_ssrc4) }); | |
1571 | |
1572 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1573 | |
1574 RTCMediaStreamStats expected_local_stream( | |
1575 "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us()); | |
1576 expected_local_stream.stream_identifier = local_stream->label(); | |
1577 expected_local_stream.track_ids = std::vector<std::string>({ | |
1578 "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", | |
1579 "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2" }); | |
1580 ASSERT_TRUE(report->Get(expected_local_stream.id())); | |
1581 EXPECT_EQ(expected_local_stream, | |
1582 report->Get(expected_local_stream.id())->cast_to< | |
1583 RTCMediaStreamStats>()); | |
1584 | |
1585 RTCMediaStreamStats expected_remote_stream( | |
1586 "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us()); | |
1587 expected_remote_stream.stream_identifier = remote_stream->label(); | |
1588 expected_remote_stream.track_ids = std::vector<std::string>({ | |
1589 "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", | |
1590 "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4" }); | |
1591 ASSERT_TRUE(report->Get(expected_remote_stream.id())); | |
1592 EXPECT_EQ(expected_remote_stream, | |
1593 report->Get(expected_remote_stream.id())->cast_to< | |
1594 RTCMediaStreamStats>()); | |
1595 | |
1596 RTCMediaStreamTrackStats expected_local_video_track_ssrc1( | |
1597 "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1", | |
1598 report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); | |
1599 expected_local_video_track_ssrc1.track_identifier = local_video_track->id(); | |
1600 expected_local_video_track_ssrc1.remote_source = false; | |
1601 expected_local_video_track_ssrc1.ended = false; | |
1602 expected_local_video_track_ssrc1.detached = false; | |
1603 expected_local_video_track_ssrc1.frame_width = 1234; | |
1604 expected_local_video_track_ssrc1.frame_height = 4321; | |
1605 expected_local_video_track_ssrc1.frames_sent = 11; | |
1606 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc1.id())); | |
1607 EXPECT_EQ(expected_local_video_track_ssrc1, | |
1608 report->Get(expected_local_video_track_ssrc1.id())->cast_to< | |
1609 RTCMediaStreamTrackStats>()); | |
1610 | |
1611 RTCMediaStreamTrackStats expected_local_video_track_ssrc2( | |
1612 "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2", | |
1613 report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); | |
1614 expected_local_video_track_ssrc2.track_identifier = local_video_track->id(); | |
1615 expected_local_video_track_ssrc2.remote_source = false; | |
1616 expected_local_video_track_ssrc2.ended = false; | |
1617 expected_local_video_track_ssrc2.detached = false; | |
1618 expected_local_video_track_ssrc2.frame_width = 4321; | |
1619 expected_local_video_track_ssrc2.frame_height = 1234; | |
1620 expected_local_video_track_ssrc2.frames_sent = 22; | |
1621 ASSERT_TRUE(report->Get(expected_local_video_track_ssrc2.id())); | |
1622 EXPECT_EQ(expected_local_video_track_ssrc2, | |
1623 report->Get(expected_local_video_track_ssrc2.id())->cast_to< | |
1624 RTCMediaStreamTrackStats>()); | |
1625 | |
1626 RTCMediaStreamTrackStats expected_remote_video_track_ssrc3( | |
1627 "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3", | |
1628 report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); | |
1629 expected_remote_video_track_ssrc3.track_identifier = | |
1630 remote_video_track_ssrc3->id(); | |
1631 expected_remote_video_track_ssrc3.remote_source = true; | |
1632 expected_remote_video_track_ssrc3.ended = true; | |
1633 expected_remote_video_track_ssrc3.detached = false; | |
1634 expected_remote_video_track_ssrc3.frame_width = 6789; | |
1635 expected_remote_video_track_ssrc3.frame_height = 9876; | |
1636 expected_remote_video_track_ssrc3.frames_received = 2468; | |
1637 expected_remote_video_track_ssrc3.frames_decoded = 1234; | |
1638 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc3.id())); | |
1639 EXPECT_EQ(expected_remote_video_track_ssrc3, | |
1640 report->Get(expected_remote_video_track_ssrc3.id())->cast_to< | |
1641 RTCMediaStreamTrackStats>()); | |
1642 | |
1643 RTCMediaStreamTrackStats expected_remote_video_track_ssrc4( | |
1644 "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4", | |
1645 report->timestamp_us(), RTCMediaStreamTrackKind::kVideo); | |
1646 expected_remote_video_track_ssrc4.track_identifier = | |
1647 remote_video_track_ssrc4->id(); | |
1648 expected_remote_video_track_ssrc4.remote_source = true; | |
1649 expected_remote_video_track_ssrc4.ended = false; | |
1650 expected_remote_video_track_ssrc4.detached = false; | |
1651 expected_remote_video_track_ssrc4.frames_received = 0; | |
1652 expected_remote_video_track_ssrc4.frames_decoded = 0; | |
1653 // Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and | |
1654 // |expected_remote_video_track_ssrc4.frame_height|. | |
1655 ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id())); | |
1656 EXPECT_EQ(expected_remote_video_track_ssrc4, | |
1657 report->Get(expected_remote_video_track_ssrc4.id())->cast_to< | |
1658 RTCMediaStreamTrackStats>()); | |
1659 } | |
1660 | |
1661 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) { | |
1662 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); | |
1663 cricket::VoiceChannel voice_channel( | |
1664 test_->worker_thread(), test_->network_thread(), | |
1665 test_->signaling_thread(), test_->media_engine(), voice_media_channel, | |
1666 "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1667 | |
1668 test_->SetupRemoteTrackAndReceiver( | |
1669 cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID", 1); | |
1670 | |
1671 cricket::VoiceMediaInfo voice_media_info; | |
1672 | |
1673 voice_media_info.receivers.push_back(cricket::VoiceReceiverInfo()); | |
1674 voice_media_info.receivers[0].local_stats.push_back( | |
1675 cricket::SsrcReceiverInfo()); | |
1676 voice_media_info.receivers[0].local_stats[0].ssrc = 1; | |
1677 voice_media_info.receivers[0].packets_lost = 42; | |
1678 voice_media_info.receivers[0].packets_rcvd = 2; | |
1679 voice_media_info.receivers[0].bytes_rcvd = 3; | |
1680 voice_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42); | |
1681 voice_media_info.receivers[0].jitter_ms = 4500; | |
1682 voice_media_info.receivers[0].fraction_lost = 5.5f; | |
1683 | |
1684 RtpCodecParameters codec_parameters; | |
1685 codec_parameters.payload_type = 42; | |
1686 codec_parameters.mime_type = "dummy"; | |
1687 codec_parameters.clock_rate = 0; | |
1688 voice_media_info.receive_codecs.insert( | |
1689 std::make_pair(codec_parameters.payload_type, codec_parameters)); | |
1690 | |
1691 EXPECT_CALL(*voice_media_channel, GetStats(_)) | |
1692 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true))); | |
1693 | |
1694 SessionStats session_stats; | |
1695 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName"; | |
1696 session_stats.transport_stats["TransportName"].transport_name = | |
1697 "TransportName"; | |
1698 | |
1699 // Make sure the associated |RTCTransportStats| is created. | |
1700 cricket::TransportChannelStats channel_stats; | |
1701 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
1702 session_stats.transport_stats["TransportName"].channel_stats.push_back( | |
1703 channel_stats); | |
1704 | |
1705 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1706 [&session_stats](const ChannelNamePairs&) { | |
1707 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1708 })); | |
1709 EXPECT_CALL(test_->session(), voice_channel()) | |
1710 .WillRepeatedly(Return(&voice_channel)); | |
1711 | |
1712 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1713 | |
1714 RTCInboundRTPStreamStats expected_audio( | |
1715 "RTCInboundRTPAudioStream_1", report->timestamp_us()); | |
1716 expected_audio.ssrc = "1"; | |
1717 expected_audio.is_remote = false; | |
1718 expected_audio.media_type = "audio"; | |
1719 expected_audio.media_track_id = | |
1720 "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_1"; | |
1721 expected_audio.transport_id = "RTCTransport_TransportName_" + | |
1722 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
1723 expected_audio.codec_id = "RTCCodec_InboundAudio_42"; | |
1724 expected_audio.packets_received = 2; | |
1725 expected_audio.bytes_received = 3; | |
1726 expected_audio.packets_lost = 42; | |
1727 expected_audio.jitter = 4.5; | |
1728 expected_audio.fraction_lost = 5.5; | |
1729 | |
1730 ASSERT_TRUE(report->Get(expected_audio.id())); | |
1731 const RTCInboundRTPStreamStats& audio = report->Get( | |
1732 expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(); | |
1733 EXPECT_EQ(audio, expected_audio); | |
1734 | |
1735 EXPECT_TRUE(report->Get(*expected_audio.media_track_id)); | |
1736 EXPECT_TRUE(report->Get(*expected_audio.transport_id)); | |
1737 EXPECT_TRUE(report->Get(*expected_audio.codec_id)); | |
1738 } | |
1739 | |
1740 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) { | |
1741 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); | |
1742 cricket::VideoChannel video_channel( | |
1743 test_->worker_thread(), test_->network_thread(), | |
1744 test_->signaling_thread(), video_media_channel, "VideoContentName", | |
1745 kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1746 | |
1747 test_->SetupRemoteTrackAndReceiver( | |
1748 cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID", 1); | |
1749 | |
1750 cricket::VideoMediaInfo video_media_info; | |
1751 | |
1752 video_media_info.receivers.push_back(cricket::VideoReceiverInfo()); | |
1753 video_media_info.receivers[0].local_stats.push_back( | |
1754 cricket::SsrcReceiverInfo()); | |
1755 video_media_info.receivers[0].local_stats[0].ssrc = 1; | |
1756 video_media_info.receivers[0].packets_rcvd = 2; | |
1757 video_media_info.receivers[0].packets_lost = 42; | |
1758 video_media_info.receivers[0].bytes_rcvd = 3; | |
1759 video_media_info.receivers[0].fraction_lost = 4.5f; | |
1760 video_media_info.receivers[0].codec_payload_type = rtc::Optional<int>(42); | |
1761 video_media_info.receivers[0].firs_sent = 5; | |
1762 video_media_info.receivers[0].plis_sent = 6; | |
1763 video_media_info.receivers[0].nacks_sent = 7; | |
1764 video_media_info.receivers[0].frames_decoded = 8; | |
1765 | |
1766 RtpCodecParameters codec_parameters; | |
1767 codec_parameters.payload_type = 42; | |
1768 codec_parameters.mime_type = "dummy"; | |
1769 codec_parameters.clock_rate = 0; | |
1770 video_media_info.receive_codecs.insert( | |
1771 std::make_pair(codec_parameters.payload_type, codec_parameters)); | |
1772 | |
1773 EXPECT_CALL(*video_media_channel, GetStats(_)) | |
1774 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true))); | |
1775 | |
1776 SessionStats session_stats; | |
1777 session_stats.proxy_to_transport["VideoContentName"] = "TransportName"; | |
1778 session_stats.transport_stats["TransportName"].transport_name = | |
1779 "TransportName"; | |
1780 | |
1781 // Make sure the associated |RTCTransportStats| is created. | |
1782 cricket::TransportChannelStats channel_stats; | |
1783 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
1784 session_stats.transport_stats["TransportName"].channel_stats.push_back( | |
1785 channel_stats); | |
1786 | |
1787 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1788 [&session_stats](const ChannelNamePairs&) { | |
1789 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1790 })); | |
1791 EXPECT_CALL(test_->session(), video_channel()) | |
1792 .WillRepeatedly(Return(&video_channel)); | |
1793 | |
1794 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1795 | |
1796 RTCInboundRTPStreamStats expected_video( | |
1797 "RTCInboundRTPVideoStream_1", report->timestamp_us()); | |
1798 expected_video.ssrc = "1"; | |
1799 expected_video.is_remote = false; | |
1800 expected_video.media_type = "video"; | |
1801 expected_video.media_track_id = | |
1802 "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_1"; | |
1803 expected_video.transport_id = "RTCTransport_TransportName_" + | |
1804 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
1805 expected_video.codec_id = "RTCCodec_InboundVideo_42"; | |
1806 expected_video.fir_count = 5; | |
1807 expected_video.pli_count = 6; | |
1808 expected_video.nack_count = 7; | |
1809 expected_video.packets_received = 2; | |
1810 expected_video.bytes_received = 3; | |
1811 expected_video.packets_lost = 42; | |
1812 expected_video.fraction_lost = 4.5; | |
1813 expected_video.frames_decoded = 8; | |
1814 | |
1815 ASSERT_TRUE(report->Get(expected_video.id())); | |
1816 const RTCInboundRTPStreamStats& video = report->Get( | |
1817 expected_video.id())->cast_to<RTCInboundRTPStreamStats>(); | |
1818 EXPECT_EQ(video, expected_video); | |
1819 | |
1820 EXPECT_TRUE(report->Get(*expected_video.media_track_id)); | |
1821 EXPECT_TRUE(report->Get(*expected_video.transport_id)); | |
1822 EXPECT_TRUE(report->Get(*video.codec_id)); | |
1823 } | |
1824 | |
1825 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) { | |
1826 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); | |
1827 cricket::VoiceChannel voice_channel( | |
1828 test_->worker_thread(), test_->network_thread(), | |
1829 test_->signaling_thread(), test_->media_engine(), voice_media_channel, | |
1830 "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1831 | |
1832 test_->SetupLocalTrackAndSender( | |
1833 cricket::MEDIA_TYPE_AUDIO, "LocalAudioTrackID", 1); | |
1834 | |
1835 cricket::VoiceMediaInfo voice_media_info; | |
1836 | |
1837 voice_media_info.senders.push_back(cricket::VoiceSenderInfo()); | |
1838 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); | |
1839 voice_media_info.senders[0].local_stats[0].ssrc = 1; | |
1840 voice_media_info.senders[0].packets_sent = 2; | |
1841 voice_media_info.senders[0].bytes_sent = 3; | |
1842 voice_media_info.senders[0].rtt_ms = 4500; | |
1843 voice_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42); | |
1844 | |
1845 RtpCodecParameters codec_parameters; | |
1846 codec_parameters.payload_type = 42; | |
1847 codec_parameters.mime_type = "dummy"; | |
1848 codec_parameters.clock_rate = 0; | |
1849 voice_media_info.send_codecs.insert( | |
1850 std::make_pair(codec_parameters.payload_type, codec_parameters)); | |
1851 | |
1852 EXPECT_CALL(*voice_media_channel, GetStats(_)) | |
1853 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true))); | |
1854 | |
1855 SessionStats session_stats; | |
1856 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName"; | |
1857 session_stats.transport_stats["TransportName"].transport_name = | |
1858 "TransportName"; | |
1859 | |
1860 // Make sure the associated |RTCTransportStats| is created. | |
1861 cricket::TransportChannelStats channel_stats; | |
1862 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
1863 session_stats.transport_stats["TransportName"].channel_stats.push_back( | |
1864 channel_stats); | |
1865 | |
1866 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1867 [&session_stats](const ChannelNamePairs&) { | |
1868 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1869 })); | |
1870 EXPECT_CALL(test_->session(), voice_channel()) | |
1871 .WillRepeatedly(Return(&voice_channel)); | |
1872 | |
1873 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1874 | |
1875 RTCOutboundRTPStreamStats expected_audio( | |
1876 "RTCOutboundRTPAudioStream_1", report->timestamp_us()); | |
1877 expected_audio.ssrc = "1"; | |
1878 expected_audio.is_remote = false; | |
1879 expected_audio.media_type = "audio"; | |
1880 expected_audio.media_track_id = | |
1881 "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1"; | |
1882 expected_audio.transport_id = "RTCTransport_TransportName_" + | |
1883 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
1884 expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; | |
1885 expected_audio.packets_sent = 2; | |
1886 expected_audio.bytes_sent = 3; | |
1887 expected_audio.round_trip_time = 4.5; | |
1888 | |
1889 ASSERT_TRUE(report->Get(expected_audio.id())); | |
1890 const RTCOutboundRTPStreamStats& audio = report->Get( | |
1891 expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(); | |
1892 EXPECT_EQ(audio, expected_audio); | |
1893 | |
1894 EXPECT_TRUE(report->Get(*expected_audio.media_track_id)); | |
1895 EXPECT_TRUE(report->Get(*expected_audio.transport_id)); | |
1896 EXPECT_TRUE(report->Get(*expected_audio.codec_id)); | |
1897 } | |
1898 | |
1899 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) { | |
1900 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); | |
1901 cricket::VideoChannel video_channel( | |
1902 test_->worker_thread(), test_->network_thread(), | |
1903 test_->signaling_thread(), video_media_channel, "VideoContentName", | |
1904 kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1905 | |
1906 test_->SetupLocalTrackAndSender( | |
1907 cricket::MEDIA_TYPE_VIDEO, "LocalVideoTrackID", 1); | |
1908 | |
1909 cricket::VideoMediaInfo video_media_info; | |
1910 | |
1911 video_media_info.senders.push_back(cricket::VideoSenderInfo()); | |
1912 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); | |
1913 video_media_info.senders[0].local_stats[0].ssrc = 1; | |
1914 video_media_info.senders[0].firs_rcvd = 2; | |
1915 video_media_info.senders[0].plis_rcvd = 3; | |
1916 video_media_info.senders[0].nacks_rcvd = 4; | |
1917 video_media_info.senders[0].packets_sent = 5; | |
1918 video_media_info.senders[0].bytes_sent = 6; | |
1919 video_media_info.senders[0].rtt_ms = 7500; | |
1920 video_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42); | |
1921 video_media_info.senders[0].frames_encoded = 8; | |
1922 video_media_info.senders[0].qp_sum = rtc::Optional<uint64_t>(16); | |
1923 | |
1924 RtpCodecParameters codec_parameters; | |
1925 codec_parameters.payload_type = 42; | |
1926 codec_parameters.mime_type = "dummy"; | |
1927 codec_parameters.clock_rate = 0; | |
1928 video_media_info.send_codecs.insert( | |
1929 std::make_pair(codec_parameters.payload_type, codec_parameters)); | |
1930 | |
1931 EXPECT_CALL(*video_media_channel, GetStats(_)) | |
1932 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true))); | |
1933 | |
1934 SessionStats session_stats; | |
1935 session_stats.proxy_to_transport["VideoContentName"] = "TransportName"; | |
1936 session_stats.transport_stats["TransportName"].transport_name = | |
1937 "TransportName"; | |
1938 | |
1939 // Make sure the associated |RTCTransportStats| is created. | |
1940 cricket::TransportChannelStats channel_stats; | |
1941 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
1942 session_stats.transport_stats["TransportName"].channel_stats.push_back( | |
1943 channel_stats); | |
1944 | |
1945 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
1946 [&session_stats](const ChannelNamePairs&) { | |
1947 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
1948 })); | |
1949 EXPECT_CALL(test_->session(), video_channel()) | |
1950 .WillRepeatedly(Return(&video_channel)); | |
1951 | |
1952 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
1953 | |
1954 RTCOutboundRTPStreamStats expected_video( | |
1955 "RTCOutboundRTPVideoStream_1", report->timestamp_us()); | |
1956 expected_video.ssrc = "1"; | |
1957 expected_video.is_remote = false; | |
1958 expected_video.media_type = "video"; | |
1959 expected_video.media_track_id = | |
1960 "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1"; | |
1961 expected_video.transport_id = "RTCTransport_TransportName_" + | |
1962 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
1963 expected_video.codec_id = "RTCCodec_OutboundVideo_42"; | |
1964 expected_video.fir_count = 2; | |
1965 expected_video.pli_count = 3; | |
1966 expected_video.nack_count = 4; | |
1967 expected_video.packets_sent = 5; | |
1968 expected_video.bytes_sent = 6; | |
1969 expected_video.round_trip_time = 7.5; | |
1970 expected_video.frames_encoded = 8; | |
1971 expected_video.qp_sum = 16; | |
1972 | |
1973 ASSERT_TRUE(report->Get(expected_video.id())); | |
1974 const RTCOutboundRTPStreamStats& video = report->Get( | |
1975 expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(); | |
1976 EXPECT_EQ(video, expected_video); | |
1977 | |
1978 EXPECT_TRUE(report->Get(*expected_video.media_track_id)); | |
1979 EXPECT_TRUE(report->Get(*expected_video.transport_id)); | |
1980 EXPECT_TRUE(report->Get(*expected_video.codec_id)); | |
1981 } | |
1982 | |
1983 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Default) { | |
1984 MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel(); | |
1985 cricket::VoiceChannel voice_channel( | |
1986 test_->worker_thread(), test_->network_thread(), | |
1987 test_->signaling_thread(), test_->media_engine(), voice_media_channel, | |
1988 "VoiceContentName", kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1989 MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel(); | |
1990 cricket::VideoChannel video_channel( | |
1991 test_->worker_thread(), test_->network_thread(), | |
1992 test_->signaling_thread(), video_media_channel, "VideoContentName", | |
1993 kDefaultRtcpMuxRequired, kDefaultSrtpRequired); | |
1994 | |
1995 cricket::VoiceMediaInfo voice_media_info; | |
1996 voice_media_info.senders.push_back(cricket::VoiceSenderInfo()); | |
1997 voice_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); | |
1998 voice_media_info.senders[0].local_stats[0].ssrc = 1; | |
1999 voice_media_info.senders[0].packets_sent = 2; | |
2000 voice_media_info.senders[0].bytes_sent = 3; | |
2001 voice_media_info.senders[0].rtt_ms = -1; | |
2002 voice_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42); | |
2003 | |
2004 cricket::VideoMediaInfo video_media_info; | |
2005 video_media_info.senders.push_back(cricket::VideoSenderInfo()); | |
2006 video_media_info.senders[0].local_stats.push_back(cricket::SsrcSenderInfo()); | |
2007 video_media_info.senders[0].local_stats[0].ssrc = 1; | |
2008 video_media_info.senders[0].firs_rcvd = 2; | |
2009 video_media_info.senders[0].plis_rcvd = 3; | |
2010 video_media_info.senders[0].nacks_rcvd = 4; | |
2011 video_media_info.senders[0].packets_sent = 5; | |
2012 video_media_info.senders[0].bytes_sent = 6; | |
2013 video_media_info.senders[0].rtt_ms = -1; | |
2014 video_media_info.senders[0].codec_payload_type = rtc::Optional<int>(42); | |
2015 video_media_info.senders[0].frames_encoded = 7; | |
2016 | |
2017 EXPECT_CALL(*voice_media_channel, GetStats(_)) | |
2018 .WillOnce(DoAll(SetArgPointee<0>(voice_media_info), Return(true))); | |
2019 EXPECT_CALL(*video_media_channel, GetStats(_)) | |
2020 .WillOnce(DoAll(SetArgPointee<0>(video_media_info), Return(true))); | |
2021 | |
2022 SessionStats session_stats; | |
2023 session_stats.proxy_to_transport["VoiceContentName"] = "TransportName"; | |
2024 session_stats.proxy_to_transport["VideoContentName"] = "TransportName"; | |
2025 session_stats.transport_stats["TransportName"].transport_name = | |
2026 "TransportName"; | |
2027 | |
2028 // Make sure the associated |RTCTransportStats| is created. | |
2029 cricket::TransportChannelStats channel_stats; | |
2030 channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
2031 session_stats.transport_stats["TransportName"].channel_stats.push_back( | |
2032 channel_stats); | |
2033 | |
2034 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
2035 [&session_stats](const ChannelNamePairs&) { | |
2036 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
2037 })); | |
2038 EXPECT_CALL(test_->session(), voice_channel()) | |
2039 .WillRepeatedly(Return(&voice_channel)); | |
2040 EXPECT_CALL(test_->session(), video_channel()) | |
2041 .WillRepeatedly(Return(&video_channel)); | |
2042 | |
2043 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
2044 | |
2045 RTCOutboundRTPStreamStats expected_audio( | |
2046 "RTCOutboundRTPAudioStream_1", report->timestamp_us()); | |
2047 expected_audio.ssrc = "1"; | |
2048 expected_audio.is_remote = false; | |
2049 expected_audio.media_type = "audio"; | |
2050 expected_audio.transport_id = "RTCTransport_TransportName_" + | |
2051 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
2052 expected_audio.codec_id = "RTCCodec_OutboundAudio_42"; | |
2053 expected_audio.packets_sent = 2; | |
2054 expected_audio.bytes_sent = 3; | |
2055 // |expected_audio.round_trip_time| should be undefined. | |
2056 | |
2057 ASSERT_TRUE(report->Get(expected_audio.id())); | |
2058 const RTCOutboundRTPStreamStats& audio = report->Get( | |
2059 expected_audio.id())->cast_to<RTCOutboundRTPStreamStats>(); | |
2060 EXPECT_EQ(audio, expected_audio); | |
2061 | |
2062 RTCOutboundRTPStreamStats expected_video( | |
2063 "RTCOutboundRTPVideoStream_1", report->timestamp_us()); | |
2064 expected_video.ssrc = "1"; | |
2065 expected_video.is_remote = false; | |
2066 expected_video.media_type = "video"; | |
2067 expected_video.transport_id = "RTCTransport_TransportName_" + | |
2068 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP); | |
2069 expected_video.codec_id = "RTCCodec_OutboundVideo_42"; | |
2070 expected_video.fir_count = 2; | |
2071 expected_video.pli_count = 3; | |
2072 expected_video.nack_count = 4; | |
2073 expected_video.packets_sent = 5; | |
2074 expected_video.bytes_sent = 6; | |
2075 expected_video.frames_encoded = 7; | |
2076 // |expected_video.round_trip_time| should be undefined. | |
2077 // |expected_video.qp_sum| should be undefined. | |
2078 | |
2079 ASSERT_TRUE(report->Get(expected_video.id())); | |
2080 const RTCOutboundRTPStreamStats& video = report->Get( | |
2081 expected_video.id())->cast_to<RTCOutboundRTPStreamStats>(); | |
2082 EXPECT_EQ(video, expected_video); | |
2083 } | |
2084 | |
2085 TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { | |
2086 std::unique_ptr<cricket::Candidate> rtp_local_candidate = CreateFakeCandidate( | |
2087 "42.42.42.42", 42, "protocol", cricket::LOCAL_PORT_TYPE, 42); | |
2088 std::unique_ptr<cricket::Candidate> rtp_remote_candidate = | |
2089 CreateFakeCandidate("42.42.42.42", 42, "protocol", | |
2090 cricket::LOCAL_PORT_TYPE, 42); | |
2091 std::unique_ptr<cricket::Candidate> rtcp_local_candidate = | |
2092 CreateFakeCandidate("42.42.42.42", 42, "protocol", | |
2093 cricket::LOCAL_PORT_TYPE, 42); | |
2094 std::unique_ptr<cricket::Candidate> rtcp_remote_candidate = | |
2095 CreateFakeCandidate("42.42.42.42", 42, "protocol", | |
2096 cricket::LOCAL_PORT_TYPE, 42); | |
2097 | |
2098 SessionStats session_stats; | |
2099 session_stats.transport_stats["transport"].transport_name = "transport"; | |
2100 | |
2101 cricket::ConnectionInfo rtp_connection_info; | |
2102 rtp_connection_info.best_connection = false; | |
2103 rtp_connection_info.local_candidate = *rtp_local_candidate.get(); | |
2104 rtp_connection_info.remote_candidate = *rtp_remote_candidate.get(); | |
2105 rtp_connection_info.sent_total_bytes = 42; | |
2106 rtp_connection_info.recv_total_bytes = 1337; | |
2107 cricket::TransportChannelStats rtp_transport_channel_stats; | |
2108 rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; | |
2109 rtp_transport_channel_stats.connection_infos.push_back(rtp_connection_info); | |
2110 rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_NEW; | |
2111 session_stats.transport_stats["transport"].channel_stats.push_back( | |
2112 rtp_transport_channel_stats); | |
2113 | |
2114 | |
2115 // Mock the session to return the desired candidates. | |
2116 EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke( | |
2117 [&session_stats](const ChannelNamePairs&) { | |
2118 return std::unique_ptr<SessionStats>(new SessionStats(session_stats)); | |
2119 })); | |
2120 | |
2121 // Get stats without RTCP, an active connection or certificates. | |
2122 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport(); | |
2123 | |
2124 RTCTransportStats expected_rtp_transport( | |
2125 "RTCTransport_transport_" + | |
2126 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP), | |
2127 report->timestamp_us()); | |
2128 expected_rtp_transport.bytes_sent = 42; | |
2129 expected_rtp_transport.bytes_received = 1337; | |
2130 expected_rtp_transport.dtls_state = RTCDtlsTransportState::kNew; | |
2131 | |
2132 ASSERT_TRUE(report->Get(expected_rtp_transport.id())); | |
2133 EXPECT_EQ( | |
2134 expected_rtp_transport, | |
2135 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>()); | |
2136 | |
2137 cricket::ConnectionInfo rtcp_connection_info; | |
2138 rtcp_connection_info.best_connection = false; | |
2139 rtcp_connection_info.local_candidate = *rtcp_local_candidate.get(); | |
2140 rtcp_connection_info.remote_candidate = *rtcp_remote_candidate.get(); | |
2141 rtcp_connection_info.sent_total_bytes = 1337; | |
2142 rtcp_connection_info.recv_total_bytes = 42; | |
2143 cricket::TransportChannelStats rtcp_transport_channel_stats; | |
2144 rtcp_transport_channel_stats.component = | |
2145 cricket::ICE_CANDIDATE_COMPONENT_RTCP; | |
2146 rtcp_transport_channel_stats.connection_infos.push_back(rtcp_connection_info); | |
2147 rtcp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTING; | |
2148 session_stats.transport_stats["transport"].channel_stats.push_back( | |
2149 rtcp_transport_channel_stats); | |
2150 | |
2151 collector_->ClearCachedStatsReport(); | |
2152 // Get stats with RTCP and without an active connection or certificates. | |
2153 report = GetStatsReport(); | |
2154 | |
2155 RTCTransportStats expected_rtcp_transport( | |
2156 "RTCTransport_transport_" + | |
2157 rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTCP), | |
2158 report->timestamp_us()); | |
2159 expected_rtcp_transport.bytes_sent = 1337; | |
2160 expected_rtcp_transport.bytes_received = 42; | |
2161 expected_rtcp_transport.dtls_state = RTCDtlsTransportState::kConnecting; | |
2162 | |
2163 expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id(); | |
2164 | |
2165 ASSERT_TRUE(report->Get(expected_rtp_transport.id())); | |
2166 EXPECT_EQ( | |
2167 expected_rtp_transport, | |
2168 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>()); | |
2169 ASSERT_TRUE(report->Get(expected_rtcp_transport.id())); | |
2170 EXPECT_EQ( | |
2171 expected_rtcp_transport, | |
2172 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>()); | |
2173 | |
2174 // Get stats with an active connection (selected candidate pair). | |
2175 session_stats.transport_stats["transport"] | |
2176 .channel_stats[1] | |
2177 .connection_infos[0] | |
2178 .best_connection = true; | |
2179 | |
2180 collector_->ClearCachedStatsReport(); | |
2181 report = GetStatsReport(); | |
2182 | |
2183 expected_rtcp_transport.selected_candidate_pair_id = | |
2184 "RTCIceCandidatePair_" + rtcp_local_candidate->id() + "_" + | |
2185 rtcp_remote_candidate->id(); | |
2186 | |
2187 ASSERT_TRUE(report->Get(expected_rtp_transport.id())); | |
2188 EXPECT_EQ( | |
2189 expected_rtp_transport, | |
2190 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>()); | |
2191 ASSERT_TRUE(report->Get(expected_rtcp_transport.id())); | |
2192 EXPECT_EQ( | |
2193 expected_rtcp_transport, | |
2194 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>()); | |
2195 | |
2196 // Get stats with certificates. | |
2197 std::unique_ptr<CertificateInfo> local_certinfo = | |
2198 CreateFakeCertificateAndInfoFromDers( | |
2199 std::vector<std::string>({ "(local) local", "(local) chain" })); | |
2200 std::unique_ptr<CertificateInfo> remote_certinfo = | |
2201 CreateFakeCertificateAndInfoFromDers( | |
2202 std::vector<std::string>({ "(remote) local", "(remote) chain" })); | |
2203 EXPECT_CALL(test_->session(), GetLocalCertificate(_, _)).WillRepeatedly( | |
2204 Invoke([this, &local_certinfo](const std::string& transport_name, | |
2205 rtc::scoped_refptr<rtc::RTCCertificate>* certificate) { | |
2206 if (transport_name == "transport") { | |
2207 *certificate = local_certinfo->certificate; | |
2208 return true; | |
2209 } | |
2210 return false; | |
2211 })); | |
2212 EXPECT_CALL(test_->session(), | |
2213 GetRemoteSSLCertificate_ReturnsRawPointer(_)).WillRepeatedly(Invoke( | |
2214 [this, &remote_certinfo](const std::string& transport_name) { | |
2215 if (transport_name == "transport") | |
2216 return remote_certinfo->certificate->ssl_certificate().GetReference(); | |
2217 return static_cast<rtc::SSLCertificate*>(nullptr); | |
2218 })); | |
2219 | |
2220 collector_->ClearCachedStatsReport(); | |
2221 report = GetStatsReport(); | |
2222 | |
2223 expected_rtp_transport.local_certificate_id = | |
2224 "RTCCertificate_" + local_certinfo->fingerprints[0]; | |
2225 expected_rtp_transport.remote_certificate_id = | |
2226 "RTCCertificate_" + remote_certinfo->fingerprints[0]; | |
2227 | |
2228 expected_rtcp_transport.local_certificate_id = | |
2229 *expected_rtp_transport.local_certificate_id; | |
2230 expected_rtcp_transport.remote_certificate_id = | |
2231 *expected_rtp_transport.remote_certificate_id; | |
2232 | |
2233 ASSERT_TRUE(report->Get(expected_rtp_transport.id())); | |
2234 EXPECT_EQ( | |
2235 expected_rtp_transport, | |
2236 report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>()); | |
2237 ASSERT_TRUE(report->Get(expected_rtcp_transport.id())); | |
2238 EXPECT_EQ( | |
2239 expected_rtcp_transport, | |
2240 report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>()); | |
2241 } | |
2242 | |
2243 class RTCStatsCollectorTestWithFakeCollector : public testing::Test { | |
2244 public: | |
2245 RTCStatsCollectorTestWithFakeCollector() | |
2246 : test_(new rtc::RefCountedObject<RTCStatsCollectorTestHelper>()), | |
2247 collector_(FakeRTCStatsCollector::Create( | |
2248 &test_->pc(), 50 * rtc::kNumMicrosecsPerMillisec)) { | |
2249 } | |
2250 | |
2251 protected: | |
2252 rtc::scoped_refptr<RTCStatsCollectorTestHelper> test_; | |
2253 rtc::scoped_refptr<FakeRTCStatsCollector> collector_; | |
2254 }; | |
2255 | |
2256 TEST_F(RTCStatsCollectorTestWithFakeCollector, ThreadUsageAndResultsMerging) { | |
2257 collector_->VerifyThreadUsageAndResultsMerging(); | |
2258 } | |
2259 | |
2260 } // namespace | |
2261 | |
2262 } // namespace webrtc | |
OLD | NEW |