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