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 <set> | |
12 #include <vector> | |
13 | |
14 #include "webrtc/api/datachannelinterface.h" | |
15 #include "webrtc/api/peerconnectioninterface.h" | |
16 #include "webrtc/api/stats/rtcstats_objects.h" | |
17 #include "webrtc/api/stats/rtcstatsreport.h" | |
18 #include "webrtc/api/test/peerconnectiontestwrapper.h" | |
19 #include "webrtc/api/test/rtcstatsobtainer.h" | |
20 #include "webrtc/base/checks.h" | |
21 #include "webrtc/base/gunit.h" | |
22 #include "webrtc/base/physicalsocketserver.h" | |
23 #include "webrtc/base/refcountedobject.h" | |
24 #include "webrtc/base/scoped_ref_ptr.h" | |
25 #include "webrtc/base/virtualsocketserver.h" | |
26 | |
27 namespace webrtc { | |
28 | |
29 namespace { | |
30 | |
31 const int64_t kGetStatsTimeoutMs = 10000; | |
32 | |
33 class RTCStatsIntegrationTest : public testing::Test { | |
34 public: | |
35 RTCStatsIntegrationTest() | |
36 : physical_socket_server_(), | |
37 virtual_socket_server_(&physical_socket_server_), | |
38 network_thread_(&virtual_socket_server_), | |
39 worker_thread_() { | |
40 RTC_CHECK(network_thread_.Start()); | |
41 RTC_CHECK(worker_thread_.Start()); | |
42 | |
43 caller_ = new rtc::RefCountedObject<PeerConnectionTestWrapper>( | |
44 "caller", &network_thread_, &worker_thread_); | |
45 callee_ = new rtc::RefCountedObject<PeerConnectionTestWrapper>( | |
46 "callee", &network_thread_, &worker_thread_); | |
47 } | |
48 | |
49 void StartCall() { | |
50 // Create PeerConnections and "connect" sigslots | |
51 PeerConnectionInterface::RTCConfiguration config; | |
52 PeerConnectionInterface::IceServer ice_server; | |
53 ice_server.uri = "stun:1.1.1.1:3478"; | |
54 config.servers.push_back(ice_server); | |
55 EXPECT_TRUE(caller_->CreatePc(nullptr, config)); | |
56 EXPECT_TRUE(callee_->CreatePc(nullptr, config)); | |
57 PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get()); | |
58 | |
59 // Get user media for audio and video | |
60 caller_->GetAndAddUserMedia(true, FakeConstraints(), | |
61 true, FakeConstraints()); | |
62 callee_->GetAndAddUserMedia(true, FakeConstraints(), | |
63 true, FakeConstraints()); | |
64 | |
65 // Create data channels | |
66 DataChannelInit init; | |
67 caller_->CreateDataChannel("data", init); | |
68 callee_->CreateDataChannel("data", init); | |
69 | |
70 // Negotiate and wait for call to establish | |
71 caller_->CreateOffer(nullptr); | |
72 caller_->WaitForCallEstablished(); | |
73 callee_->WaitForCallEstablished(); | |
74 } | |
75 | |
76 rtc::scoped_refptr<const RTCStatsReport> GetStatsFromCaller() { | |
77 return GetStats(caller_->pc()); | |
78 } | |
79 | |
80 rtc::scoped_refptr<const RTCStatsReport> GetStatsFromCallee() { | |
81 return GetStats(callee_->pc()); | |
82 } | |
83 | |
84 protected: | |
85 static rtc::scoped_refptr<const RTCStatsReport> GetStats( | |
86 PeerConnectionInterface* pc) { | |
87 rtc::scoped_refptr<RTCStatsObtainer> stats_obtainer = | |
88 RTCStatsObtainer::Create(); | |
89 pc->GetStats(stats_obtainer); | |
90 EXPECT_TRUE_WAIT(stats_obtainer->report(), kGetStatsTimeoutMs); | |
91 return stats_obtainer->report(); | |
92 } | |
93 | |
94 // These objects use each other and must be constructed/destroyed in this | |
95 // order. Relationship: | |
96 // |physical_socket_server_| <- |virtual_socket_server_| <- |network_thread_| | |
97 rtc::PhysicalSocketServer physical_socket_server_; | |
98 rtc::VirtualSocketServer virtual_socket_server_; | |
99 rtc::Thread network_thread_; | |
100 rtc::Thread worker_thread_; | |
101 rtc::scoped_refptr<PeerConnectionTestWrapper> caller_; | |
102 rtc::scoped_refptr<PeerConnectionTestWrapper> callee_; | |
103 }; | |
104 | |
105 class RTCStatsVerifier { | |
106 public: | |
107 RTCStatsVerifier(const RTCStatsReport* report, const RTCStats* stats) | |
108 : report_(report), stats_(stats), all_tests_successful_(true) { | |
109 RTC_CHECK(report_); | |
110 RTC_CHECK(stats_); | |
111 for (const RTCStatsMemberInterface* member : stats_->Members()) { | |
112 untested_members_.insert(member); | |
113 } | |
114 } | |
115 | |
116 void MarkMemberTested( | |
117 const RTCStatsMemberInterface& member, bool test_successful) { | |
118 untested_members_.erase(&member); | |
119 all_tests_successful_ &= test_successful; | |
120 } | |
121 | |
122 void TestMemberIsDefined(const RTCStatsMemberInterface& member) { | |
123 EXPECT_TRUE(member.is_defined()) << | |
124 stats_->type() << "." << member.name() << "[" << stats_->id() << | |
125 "] was undefined."; | |
126 MarkMemberTested(member, member.is_defined()); | |
127 } | |
128 | |
129 void TestMemberIsUndefined(const RTCStatsMemberInterface& member) { | |
130 EXPECT_FALSE(member.is_defined()) << | |
131 stats_->type() << "." << member.name() << "[" << stats_->id() << | |
132 "] was defined (" << member.ValueToString() << ")."; | |
133 MarkMemberTested(member, !member.is_defined()); | |
134 } | |
135 | |
136 void TestMemberIsIDReference( | |
137 const RTCStatsMemberInterface& member, | |
138 const char* expected_type) { | |
139 TestMemberIsIDReference(member, expected_type, false); | |
140 } | |
141 | |
142 void TestMemberIsOptionalIDReference( | |
143 const RTCStatsMemberInterface& member, | |
144 const char* expected_type) { | |
145 TestMemberIsIDReference(member, expected_type, true); | |
146 } | |
147 | |
148 bool ExpectAllMembersSuccessfullyTested() { | |
149 if (untested_members_.empty()) | |
150 return all_tests_successful_; | |
151 for (const RTCStatsMemberInterface* member : untested_members_) { | |
152 EXPECT_TRUE(false) << | |
153 stats_->type() << "." << member->name() << "[" << stats_->id() << | |
154 "] was not tested."; | |
155 } | |
156 return false; | |
157 } | |
158 | |
159 private: | |
160 void TestMemberIsIDReference( | |
161 const RTCStatsMemberInterface& member, | |
162 const char* expected_type, | |
163 bool optional) { | |
164 if (optional && !member.is_defined()) { | |
165 MarkMemberTested(member, true); | |
166 return; | |
167 } | |
168 bool valid_reference = false; | |
169 if (member.is_defined()) { | |
170 if (member.type() == RTCStatsMemberInterface::kString) { | |
171 // A single ID. | |
172 const RTCStatsMember<std::string>& id = | |
173 member.cast_to<RTCStatsMember<std::string>>(); | |
174 const RTCStats* referenced_stats = report_->Get(*id); | |
175 valid_reference = | |
176 referenced_stats && referenced_stats->type() == expected_type; | |
177 } else if (member.type() == RTCStatsMemberInterface::kSequenceString) { | |
178 // A vector of IDs. | |
179 valid_reference = true; | |
180 const RTCStatsMember<std::vector<std::string>>& ids = | |
181 member.cast_to<RTCStatsMember<std::vector<std::string>>>(); | |
182 for (const std::string id : *ids) { | |
183 const RTCStats* referenced_stats = report_->Get(id); | |
184 if (!referenced_stats || referenced_stats->type() != expected_type) { | |
185 valid_reference = false; | |
186 break; | |
187 } | |
188 } | |
189 } | |
190 } | |
191 EXPECT_TRUE(valid_reference) << | |
192 stats_->type() << "." << member.name() << " is not a reference to an " << | |
193 "existing dictionary of type " << expected_type << " (" << | |
194 member.ValueToString() << ")."; | |
195 MarkMemberTested(member, valid_reference); | |
196 } | |
197 | |
198 rtc::scoped_refptr<const RTCStatsReport> report_; | |
199 const RTCStats* stats_; | |
200 std::set<const RTCStatsMemberInterface*> untested_members_; | |
201 bool all_tests_successful_; | |
202 }; | |
203 | |
204 class RTCStatsReportVerifier { | |
205 public: | |
206 static std::set<const char*> StatsTypes() { | |
207 std::set<const char*> stats_types; | |
208 stats_types.insert(RTCCertificateStats::kType); | |
209 stats_types.insert(RTCCodecStats::kType); | |
210 stats_types.insert(RTCDataChannelStats::kType); | |
211 stats_types.insert(RTCIceCandidatePairStats::kType); | |
212 stats_types.insert(RTCLocalIceCandidateStats::kType); | |
213 stats_types.insert(RTCRemoteIceCandidateStats::kType); | |
214 stats_types.insert(RTCMediaStreamStats::kType); | |
215 stats_types.insert(RTCMediaStreamTrackStats::kType); | |
216 stats_types.insert(RTCPeerConnectionStats::kType); | |
217 stats_types.insert(RTCInboundRTPStreamStats::kType); | |
218 stats_types.insert(RTCOutboundRTPStreamStats::kType); | |
219 stats_types.insert(RTCTransportStats::kType); | |
220 return stats_types; | |
221 } | |
222 | |
223 explicit RTCStatsReportVerifier(const RTCStatsReport* report) | |
224 : report_(report) { | |
225 } | |
226 | |
227 void VerifyReport() { | |
228 std::set<const char*> missing_stats = StatsTypes(); | |
229 bool verify_successful = true; | |
230 for (const RTCStats& stats : *report_) { | |
231 missing_stats.erase(stats.type()); | |
232 if (stats.type() == RTCCertificateStats::kType) { | |
233 verify_successful &= VerifyRTCCertificateStats( | |
234 stats.cast_to<RTCCertificateStats>()); | |
235 } else if (stats.type() == RTCCodecStats::kType) { | |
236 verify_successful &= VerifyRTCCodecStats( | |
237 stats.cast_to<RTCCodecStats>()); | |
238 } else if (stats.type() == RTCDataChannelStats::kType) { | |
239 verify_successful &= VerifyRTCDataChannelStats( | |
240 stats.cast_to<RTCDataChannelStats>()); | |
241 } else if (stats.type() == RTCIceCandidatePairStats::kType) { | |
242 verify_successful &= VerifyRTCIceCandidatePairStats( | |
243 stats.cast_to<RTCIceCandidatePairStats>()); | |
244 } else if (stats.type() == RTCLocalIceCandidateStats::kType) { | |
245 verify_successful &= VerifyRTCLocalIceCandidateStats( | |
246 stats.cast_to<RTCLocalIceCandidateStats>()); | |
247 } else if (stats.type() == RTCRemoteIceCandidateStats::kType) { | |
248 verify_successful &= VerifyRTCRemoteIceCandidateStats( | |
249 stats.cast_to<RTCRemoteIceCandidateStats>()); | |
250 } else if (stats.type() == RTCMediaStreamStats::kType) { | |
251 verify_successful &= VerifyRTCMediaStreamStats( | |
252 stats.cast_to<RTCMediaStreamStats>()); | |
253 } else if (stats.type() == RTCMediaStreamTrackStats::kType) { | |
254 verify_successful &= VerifyRTCMediaStreamTrackStats( | |
255 stats.cast_to<RTCMediaStreamTrackStats>()); | |
256 } else if (stats.type() == RTCPeerConnectionStats::kType) { | |
257 verify_successful &= VerifyRTCPeerConnectionStats( | |
258 stats.cast_to<RTCPeerConnectionStats>()); | |
259 } else if (stats.type() == RTCInboundRTPStreamStats::kType) { | |
260 verify_successful &= VerifyRTCInboundRTPStreamStats( | |
261 stats.cast_to<RTCInboundRTPStreamStats>()); | |
262 } else if (stats.type() == RTCOutboundRTPStreamStats::kType) { | |
263 verify_successful &= VerifyRTCOutboundRTPStreamStats( | |
264 stats.cast_to<RTCOutboundRTPStreamStats>()); | |
265 } else if (stats.type() == RTCTransportStats::kType) { | |
266 verify_successful &= VerifyRTCTransportStats( | |
267 stats.cast_to<RTCTransportStats>()); | |
268 } else { | |
269 EXPECT_TRUE(false) << "Unrecognized stats type: " << stats.type(); | |
270 verify_successful = false; | |
271 } | |
272 } | |
273 if (!missing_stats.empty()) { | |
274 verify_successful = false; | |
275 for (const char* missing : missing_stats) { | |
276 EXPECT_TRUE(false) << "Missing expected stats type: " << missing; | |
277 } | |
278 } | |
279 EXPECT_TRUE(verify_successful) << | |
280 "One or more problems with the stats. This is the report:\n" << | |
281 report_->ToString(); | |
282 } | |
283 | |
284 bool VerifyRTCCertificateStats( | |
285 const RTCCertificateStats& certificate) { | |
286 RTCStatsVerifier verifier(report_, &certificate); | |
287 verifier.TestMemberIsDefined(certificate.fingerprint); | |
288 verifier.TestMemberIsDefined(certificate.fingerprint_algorithm); | |
289 verifier.TestMemberIsDefined(certificate.base64_certificate); | |
290 verifier.TestMemberIsOptionalIDReference( | |
291 certificate.issuer_certificate_id, RTCCertificateStats::kType); | |
292 return verifier.ExpectAllMembersSuccessfullyTested(); | |
293 } | |
294 | |
295 bool VerifyRTCCodecStats( | |
296 const RTCCodecStats& codec) { | |
297 RTCStatsVerifier verifier(report_, &codec); | |
298 verifier.TestMemberIsDefined(codec.payload_type); | |
299 verifier.TestMemberIsDefined(codec.codec); | |
300 verifier.TestMemberIsDefined(codec.clock_rate); | |
301 verifier.TestMemberIsUndefined(codec.channels); | |
302 verifier.TestMemberIsUndefined(codec.parameters); | |
303 verifier.TestMemberIsUndefined(codec.implementation); | |
304 return verifier.ExpectAllMembersSuccessfullyTested(); | |
305 } | |
306 | |
307 bool VerifyRTCDataChannelStats( | |
308 const RTCDataChannelStats& data_channel) { | |
309 RTCStatsVerifier verifier(report_, &data_channel); | |
310 verifier.TestMemberIsDefined(data_channel.label); | |
311 verifier.TestMemberIsDefined(data_channel.protocol); | |
312 verifier.TestMemberIsDefined(data_channel.datachannelid); | |
313 verifier.TestMemberIsDefined(data_channel.state); | |
314 verifier.TestMemberIsDefined(data_channel.messages_sent); | |
315 verifier.TestMemberIsDefined(data_channel.bytes_sent); | |
316 verifier.TestMemberIsDefined(data_channel.messages_received); | |
317 verifier.TestMemberIsDefined(data_channel.bytes_received); | |
318 return verifier.ExpectAllMembersSuccessfullyTested(); | |
319 } | |
320 | |
321 bool VerifyRTCIceCandidatePairStats( | |
322 const RTCIceCandidatePairStats& candidate_pair) { | |
323 RTCStatsVerifier verifier(report_, &candidate_pair); | |
324 verifier.TestMemberIsIDReference( | |
325 candidate_pair.transport_id, RTCTransportStats::kType); | |
326 verifier.TestMemberIsIDReference( | |
327 candidate_pair.local_candidate_id, RTCLocalIceCandidateStats::kType); | |
328 verifier.TestMemberIsIDReference( | |
329 candidate_pair.remote_candidate_id, RTCRemoteIceCandidateStats::kType); | |
330 verifier.TestMemberIsUndefined(candidate_pair.state); | |
331 verifier.TestMemberIsUndefined(candidate_pair.priority); | |
332 verifier.TestMemberIsUndefined(candidate_pair.nominated); | |
333 verifier.TestMemberIsDefined(candidate_pair.writable); | |
334 verifier.TestMemberIsUndefined(candidate_pair.readable); | |
335 verifier.TestMemberIsDefined(candidate_pair.bytes_sent); | |
336 verifier.TestMemberIsDefined(candidate_pair.bytes_received); | |
337 verifier.TestMemberIsUndefined(candidate_pair.total_round_trip_time); | |
338 verifier.TestMemberIsDefined(candidate_pair.current_round_trip_time); | |
339 verifier.TestMemberIsUndefined(candidate_pair.available_outgoing_bitrate); | |
340 verifier.TestMemberIsUndefined(candidate_pair.available_incoming_bitrate); | |
341 verifier.TestMemberIsDefined(candidate_pair.requests_received); | |
342 verifier.TestMemberIsDefined(candidate_pair.requests_sent); | |
343 verifier.TestMemberIsDefined(candidate_pair.responses_received); | |
344 verifier.TestMemberIsDefined(candidate_pair.responses_sent); | |
345 verifier.TestMemberIsUndefined(candidate_pair.retransmissions_received); | |
346 verifier.TestMemberIsUndefined(candidate_pair.retransmissions_sent); | |
347 verifier.TestMemberIsUndefined(candidate_pair.consent_requests_received); | |
348 verifier.TestMemberIsDefined(candidate_pair.consent_requests_sent); | |
349 verifier.TestMemberIsUndefined(candidate_pair.consent_responses_received); | |
350 verifier.TestMemberIsUndefined(candidate_pair.consent_responses_sent); | |
351 return verifier.ExpectAllMembersSuccessfullyTested(); | |
352 } | |
353 | |
354 bool VerifyRTCIceCandidateStats( | |
355 const RTCIceCandidateStats& candidate) { | |
356 RTCStatsVerifier verifier(report_, &candidate); | |
357 verifier.TestMemberIsDefined(candidate.ip); | |
358 verifier.TestMemberIsDefined(candidate.port); | |
359 verifier.TestMemberIsDefined(candidate.protocol); | |
360 verifier.TestMemberIsDefined(candidate.candidate_type); | |
361 verifier.TestMemberIsDefined(candidate.priority); | |
362 verifier.TestMemberIsUndefined(candidate.url); | |
363 return verifier.ExpectAllMembersSuccessfullyTested(); | |
364 } | |
365 | |
366 bool VerifyRTCLocalIceCandidateStats( | |
367 const RTCLocalIceCandidateStats& local_candidate) { | |
368 return VerifyRTCIceCandidateStats(local_candidate); | |
369 } | |
370 | |
371 bool VerifyRTCRemoteIceCandidateStats( | |
372 const RTCRemoteIceCandidateStats& remote_candidate) { | |
373 return VerifyRTCIceCandidateStats(remote_candidate); | |
374 } | |
375 | |
376 bool VerifyRTCMediaStreamStats( | |
377 const RTCMediaStreamStats& media_stream) { | |
378 RTCStatsVerifier verifier(report_, &media_stream); | |
379 verifier.TestMemberIsDefined(media_stream.stream_identifier); | |
380 verifier.TestMemberIsIDReference( | |
381 media_stream.track_ids, RTCMediaStreamTrackStats::kType); | |
382 return verifier.ExpectAllMembersSuccessfullyTested(); | |
383 } | |
384 | |
385 bool VerifyRTCMediaStreamTrackStats( | |
386 const RTCMediaStreamTrackStats& media_stream_track) { | |
387 RTCStatsVerifier verifier(report_, &media_stream_track); | |
388 verifier.TestMemberIsDefined(media_stream_track.track_identifier); | |
389 verifier.TestMemberIsDefined(media_stream_track.remote_source); | |
390 verifier.TestMemberIsDefined(media_stream_track.ended); | |
391 verifier.TestMemberIsDefined(media_stream_track.detached); | |
392 verifier.TestMemberIsUndefined(media_stream_track.ssrc_ids); | |
393 // Video or audio media stream track? | |
394 if (media_stream_track.frame_width.is_defined()) { | |
395 // Video-only members | |
396 verifier.TestMemberIsDefined(media_stream_track.frame_width); | |
397 verifier.TestMemberIsDefined(media_stream_track.frame_height); | |
398 verifier.TestMemberIsUndefined(media_stream_track.frames_per_second); | |
399 verifier.TestMemberIsUndefined(media_stream_track.frames_sent); | |
400 verifier.TestMemberIsUndefined(media_stream_track.frames_received); | |
401 verifier.TestMemberIsUndefined(media_stream_track.frames_decoded); | |
402 verifier.TestMemberIsUndefined(media_stream_track.frames_dropped); | |
403 verifier.TestMemberIsUndefined(media_stream_track.frames_corrupted); | |
404 verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost); | |
405 verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost); | |
406 // Audio-only members should be undefined | |
407 verifier.TestMemberIsUndefined(media_stream_track.audio_level); | |
408 verifier.TestMemberIsUndefined(media_stream_track.echo_return_loss); | |
409 verifier.TestMemberIsUndefined( | |
410 media_stream_track.echo_return_loss_enhancement); | |
411 } else { | |
412 // Video-only members should be undefined | |
413 verifier.TestMemberIsUndefined(media_stream_track.frame_width); | |
414 verifier.TestMemberIsUndefined(media_stream_track.frame_height); | |
415 verifier.TestMemberIsUndefined(media_stream_track.frames_per_second); | |
416 verifier.TestMemberIsUndefined(media_stream_track.frames_sent); | |
417 verifier.TestMemberIsUndefined(media_stream_track.frames_received); | |
418 verifier.TestMemberIsUndefined(media_stream_track.frames_decoded); | |
419 verifier.TestMemberIsUndefined(media_stream_track.frames_dropped); | |
420 verifier.TestMemberIsUndefined(media_stream_track.frames_corrupted); | |
421 verifier.TestMemberIsUndefined(media_stream_track.partial_frames_lost); | |
422 verifier.TestMemberIsUndefined(media_stream_track.full_frames_lost); | |
423 // Audio-only members | |
424 // TODO(hbos): Why are the audio track missing |audio_level|, | |
425 // |echo_return_loss| and |echo_return_loss_enhancement|? Is this a real | |
426 // problem or does it have to do with testing and not using real devices? | |
427 // crbug.com/627816 | |
428 verifier.MarkMemberTested(media_stream_track.audio_level, true); | |
429 verifier.MarkMemberTested(media_stream_track.echo_return_loss, true); | |
430 verifier.MarkMemberTested( | |
431 media_stream_track.echo_return_loss_enhancement, true); | |
432 } | |
433 return verifier.ExpectAllMembersSuccessfullyTested(); | |
434 } | |
435 | |
436 bool VerifyRTCPeerConnectionStats( | |
437 const RTCPeerConnectionStats& peer_connection) { | |
438 RTCStatsVerifier verifier(report_, &peer_connection); | |
439 verifier.TestMemberIsDefined(peer_connection.data_channels_opened); | |
440 verifier.TestMemberIsDefined(peer_connection.data_channels_closed); | |
441 return verifier.ExpectAllMembersSuccessfullyTested(); | |
442 } | |
443 | |
444 void VerifyRTCRTPStreamStats( | |
445 const RTCRTPStreamStats& stream, RTCStatsVerifier* verifier) { | |
446 verifier->TestMemberIsDefined(stream.ssrc); | |
447 verifier->TestMemberIsUndefined(stream.associate_stats_id); | |
448 verifier->TestMemberIsDefined(stream.is_remote); | |
449 verifier->TestMemberIsDefined(stream.media_type); | |
450 verifier->TestMemberIsUndefined(stream.media_track_id); | |
451 verifier->TestMemberIsIDReference( | |
452 stream.transport_id, RTCTransportStats::kType); | |
453 verifier->TestMemberIsIDReference(stream.codec_id, RTCCodecStats::kType); | |
454 if (stream.media_type.is_defined() && *stream.media_type == "video") { | |
455 verifier->TestMemberIsDefined(stream.fir_count); | |
456 verifier->TestMemberIsDefined(stream.pli_count); | |
457 verifier->TestMemberIsDefined(stream.nack_count); | |
458 } else { | |
459 verifier->TestMemberIsUndefined(stream.fir_count); | |
460 verifier->TestMemberIsUndefined(stream.pli_count); | |
461 verifier->TestMemberIsUndefined(stream.nack_count); | |
462 } | |
463 verifier->TestMemberIsUndefined(stream.sli_count); | |
464 } | |
465 | |
466 bool VerifyRTCInboundRTPStreamStats( | |
467 const RTCInboundRTPStreamStats& inbound_stream) { | |
468 RTCStatsVerifier verifier(report_, &inbound_stream); | |
469 VerifyRTCRTPStreamStats(inbound_stream, &verifier); | |
470 verifier.TestMemberIsDefined(inbound_stream.packets_received); | |
471 verifier.TestMemberIsDefined(inbound_stream.bytes_received); | |
472 verifier.TestMemberIsDefined(inbound_stream.packets_lost); | |
473 if (inbound_stream.media_type.is_defined() && | |
474 *inbound_stream.media_type == "video") { | |
475 verifier.TestMemberIsUndefined(inbound_stream.jitter); | |
476 } else { | |
477 verifier.TestMemberIsDefined(inbound_stream.jitter); | |
478 } | |
479 verifier.TestMemberIsDefined(inbound_stream.fraction_lost); | |
480 verifier.TestMemberIsUndefined(inbound_stream.packets_discarded); | |
481 verifier.TestMemberIsUndefined(inbound_stream.packets_repaired); | |
482 verifier.TestMemberIsUndefined(inbound_stream.burst_packets_lost); | |
483 verifier.TestMemberIsUndefined(inbound_stream.burst_packets_discarded); | |
484 verifier.TestMemberIsUndefined(inbound_stream.burst_loss_count); | |
485 verifier.TestMemberIsUndefined(inbound_stream.burst_discard_count); | |
486 verifier.TestMemberIsUndefined(inbound_stream.burst_loss_rate); | |
487 verifier.TestMemberIsUndefined(inbound_stream.burst_discard_rate); | |
488 verifier.TestMemberIsUndefined(inbound_stream.gap_loss_rate); | |
489 verifier.TestMemberIsUndefined(inbound_stream.gap_discard_rate); | |
490 return verifier.ExpectAllMembersSuccessfullyTested(); | |
491 } | |
492 | |
493 bool VerifyRTCOutboundRTPStreamStats( | |
494 const RTCOutboundRTPStreamStats& outbound_stream) { | |
495 RTCStatsVerifier verifier(report_, &outbound_stream); | |
496 VerifyRTCRTPStreamStats(outbound_stream, &verifier); | |
497 verifier.TestMemberIsDefined(outbound_stream.packets_sent); | |
498 verifier.TestMemberIsDefined(outbound_stream.bytes_sent); | |
499 verifier.TestMemberIsUndefined(outbound_stream.target_bitrate); | |
500 // TODO(hbos): Defined in video but not audio case. Why? crbug.com/669877 | |
501 verifier.MarkMemberTested(outbound_stream.round_trip_time, true); | |
502 return verifier.ExpectAllMembersSuccessfullyTested(); | |
503 } | |
504 | |
505 bool VerifyRTCTransportStats( | |
506 const RTCTransportStats& transport) { | |
507 RTCStatsVerifier verifier(report_, &transport); | |
508 verifier.TestMemberIsDefined(transport.bytes_sent); | |
509 verifier.TestMemberIsDefined(transport.bytes_received); | |
510 verifier.TestMemberIsOptionalIDReference( | |
511 transport.rtcp_transport_stats_id, RTCTransportStats::kType); | |
512 verifier.TestMemberIsDefined(transport.active_connection); | |
513 verifier.TestMemberIsIDReference( | |
514 transport.selected_candidate_pair_id, RTCIceCandidatePairStats::kType); | |
515 verifier.TestMemberIsIDReference( | |
516 transport.local_certificate_id, RTCCertificateStats::kType); | |
517 verifier.TestMemberIsIDReference( | |
518 transport.remote_certificate_id, RTCCertificateStats::kType); | |
519 return verifier.ExpectAllMembersSuccessfullyTested(); | |
520 } | |
521 | |
522 private: | |
523 rtc::scoped_refptr<const RTCStatsReport> report_; | |
524 }; | |
525 | |
526 TEST_F(RTCStatsIntegrationTest, GetStatsFromCaller) { | |
527 StartCall(); | |
528 | |
529 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsFromCaller(); | |
530 RTCStatsReportVerifier(report.get()).VerifyReport(); | |
531 } | |
532 | |
533 TEST_F(RTCStatsIntegrationTest, GetStatsFromCallee) { | |
534 StartCall(); | |
535 | |
536 rtc::scoped_refptr<const RTCStatsReport> report = GetStatsFromCallee(); | |
537 RTCStatsReportVerifier(report.get()).VerifyReport(); | |
538 } | |
539 | |
540 } // namespace | |
541 | |
542 } // namespace webrtc | |
OLD | NEW |