1 /*
2 * Copyright (c) 2015 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 "api/rtc_event_log/rtc_event_log.h"
12
13 #include <algorithm>
14 #include <limits>
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <tuple>
19 #include <utility>
20 #include <vector>
21
22 #include "api/rtc_event_log/rtc_event_log_factory.h"
23 #include "api/task_queue/default_task_queue_factory.h"
24 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
25 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
26 #include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
27 #include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
28 #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
29 #include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
30 #include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
31 #include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
32 #include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
33 #include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
34 #include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
35 #include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
36 #include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
37 #include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
38 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
39 #include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
40 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
41 #include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
42 #include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
43 #include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
44 #include "logging/rtc_event_log/rtc_event_log_parser.h"
45 #include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
46 #include "logging/rtc_event_log/rtc_stream_config.h"
47 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
48 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
49 #include "rtc_base/checks.h"
50 #include "rtc_base/fake_clock.h"
51 #include "rtc_base/random.h"
52 #include "test/gtest.h"
53 #include "test/logging/memory_log_writer.h"
54 #include "test/testsupport/file_utils.h"
55
56 namespace webrtc {
57
58 namespace {
59
60 struct EventCounts {
61 size_t audio_send_streams = 0;
62 size_t audio_recv_streams = 0;
63 size_t video_send_streams = 0;
64 size_t video_recv_streams = 0;
65 size_t alr_states = 0;
66 size_t route_changes = 0;
67 size_t audio_playouts = 0;
68 size_t ana_configs = 0;
69 size_t bwe_loss_events = 0;
70 size_t bwe_delay_events = 0;
71 size_t dtls_transport_states = 0;
72 size_t dtls_writable_states = 0;
73 size_t frame_decoded_events = 0;
74 size_t probe_creations = 0;
75 size_t probe_successes = 0;
76 size_t probe_failures = 0;
77 size_t ice_configs = 0;
78 size_t ice_events = 0;
79 size_t incoming_rtp_packets = 0;
80 size_t outgoing_rtp_packets = 0;
81 size_t incoming_rtcp_packets = 0;
82 size_t outgoing_rtcp_packets = 0;
83 size_t generic_packets_sent = 0;
84 size_t generic_packets_received = 0;
85 size_t generic_acks_received = 0;
86
total_nonconfig_eventswebrtc::__anon88f5430b0111::EventCounts87 size_t total_nonconfig_events() const {
88 return alr_states + route_changes + audio_playouts + ana_configs +
89 bwe_loss_events + bwe_delay_events + dtls_transport_states +
90 dtls_writable_states + frame_decoded_events + probe_creations +
91 probe_successes + probe_failures + ice_configs + ice_events +
92 incoming_rtp_packets + outgoing_rtp_packets + incoming_rtcp_packets +
93 outgoing_rtcp_packets + generic_packets_sent +
94 generic_packets_received + generic_acks_received;
95 }
96
total_config_eventswebrtc::__anon88f5430b0111::EventCounts97 size_t total_config_events() const {
98 return audio_send_streams + audio_recv_streams + video_send_streams +
99 video_recv_streams;
100 }
101
total_eventswebrtc::__anon88f5430b0111::EventCounts102 size_t total_events() const {
103 return total_nonconfig_events() + total_config_events();
104 }
105 };
106
107 class RtcEventLogSession
108 : public ::testing::TestWithParam<
109 std::tuple<uint64_t, int64_t, RtcEventLog::EncodingType>> {
110 public:
RtcEventLogSession()111 RtcEventLogSession()
112 : seed_(std::get<0>(GetParam())),
113 prng_(seed_),
114 output_period_ms_(std::get<1>(GetParam())),
115 encoding_type_(std::get<2>(GetParam())),
116 gen_(seed_ * 880001UL),
117 verifier_(encoding_type_),
118 log_storage_(),
119 log_output_factory_(log_storage_.CreateFactory()) {
120 clock_.SetTime(Timestamp::Micros(prng_.Rand<uint32_t>()));
121 // Find the name of the current test, in order to use it as a temporary
122 // filename.
123 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
124 std::string test_name =
125 std::string(test_info->test_case_name()) + "_" + test_info->name();
126 std::replace(test_name.begin(), test_name.end(), '/', '_');
127 temp_filename_ = test::OutputPath() + test_name;
128 }
129
130 // Create and buffer the config events and `num_events_before_log_start`
131 // randomized non-config events. Then call StartLogging and finally create and
132 // write the remaining non-config events.
133 void WriteLog(EventCounts count, size_t num_events_before_log_start);
134 void ReadAndVerifyLog();
135
IsNewFormat()136 bool IsNewFormat() {
137 return encoding_type_ == RtcEventLog::EncodingType::NewFormat;
138 }
139
140 private:
141 void WriteAudioRecvConfigs(size_t audio_recv_streams, RtcEventLog* event_log);
142 void WriteAudioSendConfigs(size_t audio_send_streams, RtcEventLog* event_log);
143 void WriteVideoRecvConfigs(size_t video_recv_streams, RtcEventLog* event_log);
144 void WriteVideoSendConfigs(size_t video_send_streams, RtcEventLog* event_log);
145
146 std::vector<std::pair<uint32_t, RtpHeaderExtensionMap>> incoming_extensions_;
147 std::vector<std::pair<uint32_t, RtpHeaderExtensionMap>> outgoing_extensions_;
148
149 // Config events.
150 std::vector<std::unique_ptr<RtcEventAudioSendStreamConfig>>
151 audio_send_config_list_;
152 std::vector<std::unique_ptr<RtcEventAudioReceiveStreamConfig>>
153 audio_recv_config_list_;
154 std::vector<std::unique_ptr<RtcEventVideoSendStreamConfig>>
155 video_send_config_list_;
156 std::vector<std::unique_ptr<RtcEventVideoReceiveStreamConfig>>
157 video_recv_config_list_;
158
159 // Regular events.
160 std::vector<std::unique_ptr<RtcEventAlrState>> alr_state_list_;
161 std::map<uint32_t, std::vector<std::unique_ptr<RtcEventAudioPlayout>>>
162 audio_playout_map_; // Groups audio by SSRC.
163 std::vector<std::unique_ptr<RtcEventAudioNetworkAdaptation>>
164 ana_configs_list_;
165 std::vector<std::unique_ptr<RtcEventBweUpdateDelayBased>> bwe_delay_list_;
166 std::vector<std::unique_ptr<RtcEventBweUpdateLossBased>> bwe_loss_list_;
167 std::vector<std::unique_ptr<RtcEventDtlsTransportState>>
168 dtls_transport_state_list_;
169 std::vector<std::unique_ptr<RtcEventDtlsWritableState>>
170 dtls_writable_state_list_;
171 std::map<uint32_t, std::vector<std::unique_ptr<RtcEventFrameDecoded>>>
172 frame_decoded_event_map_;
173 std::vector<std::unique_ptr<RtcEventGenericAckReceived>>
174 generic_acks_received_;
175 std::vector<std::unique_ptr<RtcEventGenericPacketReceived>>
176 generic_packets_received_;
177 std::vector<std::unique_ptr<RtcEventGenericPacketSent>> generic_packets_sent_;
178 std::vector<std::unique_ptr<RtcEventIceCandidatePair>> ice_event_list_;
179 std::vector<std::unique_ptr<RtcEventIceCandidatePairConfig>> ice_config_list_;
180 std::vector<std::unique_ptr<RtcEventProbeClusterCreated>>
181 probe_creation_list_;
182 std::vector<std::unique_ptr<RtcEventProbeResultFailure>> probe_failure_list_;
183 std::vector<std::unique_ptr<RtcEventProbeResultSuccess>> probe_success_list_;
184 std::vector<std::unique_ptr<RtcEventRouteChange>> route_change_list_;
185 std::vector<std::unique_ptr<RtcEventRemoteEstimate>> remote_estimate_list_;
186 std::vector<std::unique_ptr<RtcEventRtcpPacketIncoming>> incoming_rtcp_list_;
187 std::vector<std::unique_ptr<RtcEventRtcpPacketOutgoing>> outgoing_rtcp_list_;
188 std::map<uint32_t, std::vector<std::unique_ptr<RtcEventRtpPacketIncoming>>>
189 incoming_rtp_map_; // Groups incoming RTP by SSRC.
190 std::map<uint32_t, std::vector<std::unique_ptr<RtcEventRtpPacketOutgoing>>>
191 outgoing_rtp_map_; // Groups outgoing RTP by SSRC.
192
193 int64_t start_time_us_;
194 int64_t utc_start_time_us_;
195 int64_t stop_time_us_;
196
197 int64_t first_timestamp_ms_ = std::numeric_limits<int64_t>::max();
198 int64_t last_timestamp_ms_ = std::numeric_limits<int64_t>::min();
199
200 const uint64_t seed_;
201 Random prng_;
202 const int64_t output_period_ms_;
203 const RtcEventLog::EncodingType encoding_type_;
204 test::EventGenerator gen_;
205 test::EventVerifier verifier_;
206 rtc::ScopedFakeClock clock_;
207 std::string temp_filename_;
208 MemoryLogStorage log_storage_;
209 std::unique_ptr<LogWriterFactoryInterface> log_output_factory_;
210 };
211
SsrcUsed(uint32_t ssrc,const std::vector<std::pair<uint32_t,RtpHeaderExtensionMap>> & streams)212 bool SsrcUsed(
213 uint32_t ssrc,
214 const std::vector<std::pair<uint32_t, RtpHeaderExtensionMap>>& streams) {
215 for (const auto& kv : streams) {
216 if (kv.first == ssrc)
217 return true;
218 }
219 return false;
220 }
221
WriteAudioRecvConfigs(size_t audio_recv_streams,RtcEventLog * event_log)222 void RtcEventLogSession::WriteAudioRecvConfigs(size_t audio_recv_streams,
223 RtcEventLog* event_log) {
224 RTC_CHECK(event_log != nullptr);
225 uint32_t ssrc;
226 for (size_t i = 0; i < audio_recv_streams; i++) {
227 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
228 do {
229 ssrc = prng_.Rand<uint32_t>();
230 } while (SsrcUsed(ssrc, incoming_extensions_));
231 RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
232 incoming_extensions_.emplace_back(ssrc, extensions);
233 auto event = gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
234 event_log->Log(event->Copy());
235 audio_recv_config_list_.push_back(std::move(event));
236 }
237 }
238
WriteAudioSendConfigs(size_t audio_send_streams,RtcEventLog * event_log)239 void RtcEventLogSession::WriteAudioSendConfigs(size_t audio_send_streams,
240 RtcEventLog* event_log) {
241 RTC_CHECK(event_log != nullptr);
242 uint32_t ssrc;
243 for (size_t i = 0; i < audio_send_streams; i++) {
244 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
245 do {
246 ssrc = prng_.Rand<uint32_t>();
247 } while (SsrcUsed(ssrc, outgoing_extensions_));
248 RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
249 outgoing_extensions_.emplace_back(ssrc, extensions);
250 auto event = gen_.NewAudioSendStreamConfig(ssrc, extensions);
251 event_log->Log(event->Copy());
252 audio_send_config_list_.push_back(std::move(event));
253 }
254 }
255
WriteVideoRecvConfigs(size_t video_recv_streams,RtcEventLog * event_log)256 void RtcEventLogSession::WriteVideoRecvConfigs(size_t video_recv_streams,
257 RtcEventLog* event_log) {
258 RTC_CHECK(event_log != nullptr);
259 RTC_CHECK_GE(video_recv_streams, 1);
260
261 // Force least one stream to use all header extensions, to ensure
262 // (statistically) that every extension is tested in packet creation.
263 RtpHeaderExtensionMap all_extensions =
264 ParsedRtcEventLog::GetDefaultHeaderExtensionMap();
265
266 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
267 uint32_t ssrc = prng_.Rand<uint32_t>();
268 incoming_extensions_.emplace_back(ssrc, all_extensions);
269 auto event = gen_.NewVideoReceiveStreamConfig(ssrc, all_extensions);
270 event_log->Log(event->Copy());
271 video_recv_config_list_.push_back(std::move(event));
272 for (size_t i = 1; i < video_recv_streams; i++) {
273 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
274 do {
275 ssrc = prng_.Rand<uint32_t>();
276 } while (SsrcUsed(ssrc, incoming_extensions_));
277 RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
278 incoming_extensions_.emplace_back(ssrc, extensions);
279 auto new_event = gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
280 event_log->Log(new_event->Copy());
281 video_recv_config_list_.push_back(std::move(new_event));
282 }
283 }
284
WriteVideoSendConfigs(size_t video_send_streams,RtcEventLog * event_log)285 void RtcEventLogSession::WriteVideoSendConfigs(size_t video_send_streams,
286 RtcEventLog* event_log) {
287 RTC_CHECK(event_log != nullptr);
288 RTC_CHECK_GE(video_send_streams, 1);
289
290 // Force least one stream to use all header extensions, to ensure
291 // (statistically) that every extension is tested in packet creation.
292 RtpHeaderExtensionMap all_extensions =
293 ParsedRtcEventLog::GetDefaultHeaderExtensionMap();
294
295 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
296 uint32_t ssrc = prng_.Rand<uint32_t>();
297 outgoing_extensions_.emplace_back(ssrc, all_extensions);
298 auto event = gen_.NewVideoSendStreamConfig(ssrc, all_extensions);
299 event_log->Log(event->Copy());
300 video_send_config_list_.push_back(std::move(event));
301 for (size_t i = 1; i < video_send_streams; i++) {
302 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
303 do {
304 ssrc = prng_.Rand<uint32_t>();
305 } while (SsrcUsed(ssrc, outgoing_extensions_));
306 RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
307 outgoing_extensions_.emplace_back(ssrc, extensions);
308 auto event = gen_.NewVideoSendStreamConfig(ssrc, extensions);
309 event_log->Log(event->Copy());
310 video_send_config_list_.push_back(std::move(event));
311 }
312 }
313
WriteLog(EventCounts count,size_t num_events_before_start)314 void RtcEventLogSession::WriteLog(EventCounts count,
315 size_t num_events_before_start) {
316 // TODO(terelius): Allow test to run with either a real or a fake clock_.
317 // Maybe always use the ScopedFakeClock, but conditionally SleepMs()?
318
319 auto task_queue_factory = CreateDefaultTaskQueueFactory();
320 RtcEventLogFactory rtc_event_log_factory(task_queue_factory.get());
321 // The log will be flushed to output when the event_log goes out of scope.
322 std::unique_ptr<RtcEventLog> event_log =
323 rtc_event_log_factory.CreateRtcEventLog(encoding_type_);
324
325 // We can't send or receive packets without configured streams.
326 RTC_CHECK_GE(count.video_recv_streams, 1);
327 RTC_CHECK_GE(count.video_send_streams, 1);
328
329 WriteAudioRecvConfigs(count.audio_recv_streams, event_log.get());
330 WriteAudioSendConfigs(count.audio_send_streams, event_log.get());
331 WriteVideoRecvConfigs(count.video_recv_streams, event_log.get());
332 WriteVideoSendConfigs(count.video_send_streams, event_log.get());
333
334 size_t remaining_events = count.total_nonconfig_events();
335 ASSERT_LE(num_events_before_start, remaining_events);
336 size_t remaining_events_at_start = remaining_events - num_events_before_start;
337 for (; remaining_events > 0; remaining_events--) {
338 if (remaining_events == remaining_events_at_start) {
339 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
340 event_log->StartLogging(log_output_factory_->Create(temp_filename_),
341 output_period_ms_);
342 start_time_us_ = rtc::TimeMicros();
343 utc_start_time_us_ = rtc::TimeUTCMicros();
344 }
345
346 clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
347 size_t selection = prng_.Rand(remaining_events - 1);
348 first_timestamp_ms_ = std::min(first_timestamp_ms_, rtc::TimeMillis());
349 last_timestamp_ms_ = std::max(last_timestamp_ms_, rtc::TimeMillis());
350
351 if (selection < count.alr_states) {
352 auto event = gen_.NewAlrState();
353 event_log->Log(event->Copy());
354 alr_state_list_.push_back(std::move(event));
355 count.alr_states--;
356 continue;
357 }
358 selection -= count.alr_states;
359
360 if (selection < count.route_changes) {
361 auto event = gen_.NewRouteChange();
362 event_log->Log(event->Copy());
363 route_change_list_.push_back(std::move(event));
364 count.route_changes--;
365 continue;
366 }
367 selection -= count.route_changes;
368
369 if (selection < count.audio_playouts) {
370 size_t stream = prng_.Rand(incoming_extensions_.size() - 1);
371 // This might be a video SSRC, but the parser does not use the config.
372 uint32_t ssrc = incoming_extensions_[stream].first;
373 auto event = gen_.NewAudioPlayout(ssrc);
374 event_log->Log(event->Copy());
375 audio_playout_map_[ssrc].push_back(std::move(event));
376 count.audio_playouts--;
377 continue;
378 }
379 selection -= count.audio_playouts;
380
381 if (selection < count.ana_configs) {
382 auto event = gen_.NewAudioNetworkAdaptation();
383 event_log->Log(event->Copy());
384 ana_configs_list_.push_back(std::move(event));
385 count.ana_configs--;
386 continue;
387 }
388 selection -= count.ana_configs;
389
390 if (selection < count.bwe_loss_events) {
391 auto event = gen_.NewBweUpdateLossBased();
392 event_log->Log(event->Copy());
393 bwe_loss_list_.push_back(std::move(event));
394 count.bwe_loss_events--;
395 continue;
396 }
397 selection -= count.bwe_loss_events;
398
399 if (selection < count.bwe_delay_events) {
400 auto event = gen_.NewBweUpdateDelayBased();
401 event_log->Log(event->Copy());
402 bwe_delay_list_.push_back(std::move(event));
403 count.bwe_delay_events--;
404 continue;
405 }
406 selection -= count.bwe_delay_events;
407
408 if (selection < count.probe_creations) {
409 auto event = gen_.NewProbeClusterCreated();
410 event_log->Log(event->Copy());
411 probe_creation_list_.push_back(std::move(event));
412 count.probe_creations--;
413 continue;
414 }
415 selection -= count.probe_creations;
416
417 if (selection < count.probe_successes) {
418 auto event = gen_.NewProbeResultSuccess();
419 event_log->Log(event->Copy());
420 probe_success_list_.push_back(std::move(event));
421 count.probe_successes--;
422 continue;
423 }
424 selection -= count.probe_successes;
425
426 if (selection < count.probe_failures) {
427 auto event = gen_.NewProbeResultFailure();
428 event_log->Log(event->Copy());
429 probe_failure_list_.push_back(std::move(event));
430 count.probe_failures--;
431 continue;
432 }
433 selection -= count.probe_failures;
434
435 if (selection < count.dtls_transport_states) {
436 auto event = gen_.NewDtlsTransportState();
437 event_log->Log(event->Copy());
438 dtls_transport_state_list_.push_back(std::move(event));
439 count.dtls_transport_states--;
440 continue;
441 }
442 selection -= count.dtls_transport_states;
443
444 if (selection < count.dtls_writable_states) {
445 auto event = gen_.NewDtlsWritableState();
446 event_log->Log(event->Copy());
447 dtls_writable_state_list_.push_back(std::move(event));
448 count.dtls_writable_states--;
449 continue;
450 }
451 selection -= count.dtls_writable_states;
452
453 if (selection < count.frame_decoded_events) {
454 size_t stream = prng_.Rand(incoming_extensions_.size() - 1);
455 // This might be an audio SSRC, but that won't affect the parser.
456 uint32_t ssrc = incoming_extensions_[stream].first;
457 auto event = gen_.NewFrameDecodedEvent(ssrc);
458 event_log->Log(event->Copy());
459 frame_decoded_event_map_[ssrc].push_back(std::move(event));
460 count.frame_decoded_events--;
461 continue;
462 }
463 selection -= count.frame_decoded_events;
464
465 if (selection < count.ice_configs) {
466 auto event = gen_.NewIceCandidatePairConfig();
467 event_log->Log(event->Copy());
468 ice_config_list_.push_back(std::move(event));
469 count.ice_configs--;
470 continue;
471 }
472 selection -= count.ice_configs;
473
474 if (selection < count.ice_events) {
475 auto event = gen_.NewIceCandidatePair();
476 event_log->Log(event->Copy());
477 ice_event_list_.push_back(std::move(event));
478 count.ice_events--;
479 continue;
480 }
481 selection -= count.ice_events;
482
483 if (selection < count.incoming_rtp_packets) {
484 size_t stream = prng_.Rand(incoming_extensions_.size() - 1);
485 uint32_t ssrc = incoming_extensions_[stream].first;
486 auto event =
487 gen_.NewRtpPacketIncoming(ssrc, incoming_extensions_[stream].second);
488 event_log->Log(event->Copy());
489 incoming_rtp_map_[ssrc].push_back(std::move(event));
490 count.incoming_rtp_packets--;
491 continue;
492 }
493 selection -= count.incoming_rtp_packets;
494
495 if (selection < count.outgoing_rtp_packets) {
496 size_t stream = prng_.Rand(outgoing_extensions_.size() - 1);
497 uint32_t ssrc = outgoing_extensions_[stream].first;
498 auto event =
499 gen_.NewRtpPacketOutgoing(ssrc, outgoing_extensions_[stream].second);
500 event_log->Log(event->Copy());
501 outgoing_rtp_map_[ssrc].push_back(std::move(event));
502 count.outgoing_rtp_packets--;
503 continue;
504 }
505 selection -= count.outgoing_rtp_packets;
506
507 if (selection < count.incoming_rtcp_packets) {
508 auto event = gen_.NewRtcpPacketIncoming();
509 event_log->Log(event->Copy());
510 incoming_rtcp_list_.push_back(std::move(event));
511 count.incoming_rtcp_packets--;
512 continue;
513 }
514 selection -= count.incoming_rtcp_packets;
515
516 if (selection < count.outgoing_rtcp_packets) {
517 auto event = gen_.NewRtcpPacketOutgoing();
518 event_log->Log(event->Copy());
519 outgoing_rtcp_list_.push_back(std::move(event));
520 count.outgoing_rtcp_packets--;
521 continue;
522 }
523 selection -= count.outgoing_rtcp_packets;
524
525 if (selection < count.generic_packets_sent) {
526 auto event = gen_.NewGenericPacketSent();
527 generic_packets_sent_.push_back(event->Copy());
528 event_log->Log(std::move(event));
529 count.generic_packets_sent--;
530 continue;
531 }
532 selection -= count.generic_packets_sent;
533
534 if (selection < count.generic_packets_received) {
535 auto event = gen_.NewGenericPacketReceived();
536 generic_packets_received_.push_back(event->Copy());
537 event_log->Log(std::move(event));
538 count.generic_packets_received--;
539 continue;
540 }
541 selection -= count.generic_packets_received;
542
543 if (selection < count.generic_acks_received) {
544 auto event = gen_.NewGenericAckReceived();
545 generic_acks_received_.push_back(event->Copy());
546 event_log->Log(std::move(event));
547 count.generic_acks_received--;
548 continue;
549 }
550 selection -= count.generic_acks_received;
551
552 RTC_DCHECK_NOTREACHED();
553 }
554
555 event_log->StopLogging();
556 stop_time_us_ = rtc::TimeMicros();
557
558 ASSERT_EQ(count.total_nonconfig_events(), static_cast<size_t>(0));
559 }
560
561 // Read the log and verify that what we read back from the event log is the
562 // same as what we wrote down.
ReadAndVerifyLog()563 void RtcEventLogSession::ReadAndVerifyLog() {
564 // Read the generated log from memory.
565 ParsedRtcEventLog parsed_log;
566 auto it = log_storage_.logs().find(temp_filename_);
567 ASSERT_TRUE(it != log_storage_.logs().end());
568 ASSERT_TRUE(parsed_log.ParseString(it->second).ok());
569
570 // Start and stop events.
571 auto& parsed_start_log_events = parsed_log.start_log_events();
572 ASSERT_EQ(parsed_start_log_events.size(), static_cast<size_t>(1));
573 verifier_.VerifyLoggedStartEvent(start_time_us_, utc_start_time_us_,
574 parsed_start_log_events[0]);
575
576 auto& parsed_stop_log_events = parsed_log.stop_log_events();
577 ASSERT_EQ(parsed_stop_log_events.size(), static_cast<size_t>(1));
578 verifier_.VerifyLoggedStopEvent(stop_time_us_, parsed_stop_log_events[0]);
579
580 auto& parsed_alr_state_events = parsed_log.alr_state_events();
581 ASSERT_EQ(parsed_alr_state_events.size(), alr_state_list_.size());
582 for (size_t i = 0; i < parsed_alr_state_events.size(); i++) {
583 verifier_.VerifyLoggedAlrStateEvent(*alr_state_list_[i],
584 parsed_alr_state_events[i]);
585 }
586 auto& parsed_route_change_events = parsed_log.route_change_events();
587 ASSERT_EQ(parsed_route_change_events.size(), route_change_list_.size());
588 for (size_t i = 0; i < parsed_route_change_events.size(); i++) {
589 verifier_.VerifyLoggedRouteChangeEvent(*route_change_list_[i],
590 parsed_route_change_events[i]);
591 }
592
593 const auto& parsed_audio_playout_map = parsed_log.audio_playout_events();
594 ASSERT_EQ(parsed_audio_playout_map.size(), audio_playout_map_.size());
595 for (const auto& kv : parsed_audio_playout_map) {
596 uint32_t ssrc = kv.first;
597 const auto& parsed_audio_playout_stream = kv.second;
598 const auto& audio_playout_stream = audio_playout_map_[ssrc];
599 ASSERT_EQ(parsed_audio_playout_stream.size(), audio_playout_stream.size());
600 for (size_t i = 0; i < audio_playout_stream.size(); i++) {
601 verifier_.VerifyLoggedAudioPlayoutEvent(*audio_playout_stream[i],
602 parsed_audio_playout_stream[i]);
603 }
604 }
605
606 auto& parsed_audio_network_adaptation_events =
607 parsed_log.audio_network_adaptation_events();
608 ASSERT_EQ(parsed_audio_network_adaptation_events.size(),
609 ana_configs_list_.size());
610 for (size_t i = 0; i < parsed_audio_network_adaptation_events.size(); i++) {
611 verifier_.VerifyLoggedAudioNetworkAdaptationEvent(
612 *ana_configs_list_[i], parsed_audio_network_adaptation_events[i]);
613 }
614
615 auto& parsed_bwe_delay_updates = parsed_log.bwe_delay_updates();
616 ASSERT_EQ(parsed_bwe_delay_updates.size(), bwe_delay_list_.size());
617 for (size_t i = 0; i < parsed_bwe_delay_updates.size(); i++) {
618 verifier_.VerifyLoggedBweDelayBasedUpdate(*bwe_delay_list_[i],
619 parsed_bwe_delay_updates[i]);
620 }
621
622 auto& parsed_bwe_loss_updates = parsed_log.bwe_loss_updates();
623 ASSERT_EQ(parsed_bwe_loss_updates.size(), bwe_loss_list_.size());
624 for (size_t i = 0; i < parsed_bwe_loss_updates.size(); i++) {
625 verifier_.VerifyLoggedBweLossBasedUpdate(*bwe_loss_list_[i],
626 parsed_bwe_loss_updates[i]);
627 }
628
629 auto& parsed_bwe_probe_cluster_created_events =
630 parsed_log.bwe_probe_cluster_created_events();
631 ASSERT_EQ(parsed_bwe_probe_cluster_created_events.size(),
632 probe_creation_list_.size());
633 for (size_t i = 0; i < parsed_bwe_probe_cluster_created_events.size(); i++) {
634 verifier_.VerifyLoggedBweProbeClusterCreatedEvent(
635 *probe_creation_list_[i], parsed_bwe_probe_cluster_created_events[i]);
636 }
637
638 auto& parsed_bwe_probe_failure_events = parsed_log.bwe_probe_failure_events();
639 ASSERT_EQ(parsed_bwe_probe_failure_events.size(), probe_failure_list_.size());
640 for (size_t i = 0; i < parsed_bwe_probe_failure_events.size(); i++) {
641 verifier_.VerifyLoggedBweProbeFailureEvent(
642 *probe_failure_list_[i], parsed_bwe_probe_failure_events[i]);
643 }
644
645 auto& parsed_bwe_probe_success_events = parsed_log.bwe_probe_success_events();
646 ASSERT_EQ(parsed_bwe_probe_success_events.size(), probe_success_list_.size());
647 for (size_t i = 0; i < parsed_bwe_probe_success_events.size(); i++) {
648 verifier_.VerifyLoggedBweProbeSuccessEvent(
649 *probe_success_list_[i], parsed_bwe_probe_success_events[i]);
650 }
651
652 auto& parsed_dtls_transport_states = parsed_log.dtls_transport_states();
653 ASSERT_EQ(parsed_dtls_transport_states.size(),
654 dtls_transport_state_list_.size());
655 for (size_t i = 0; i < parsed_dtls_transport_states.size(); i++) {
656 verifier_.VerifyLoggedDtlsTransportState(*dtls_transport_state_list_[i],
657 parsed_dtls_transport_states[i]);
658 }
659
660 auto& parsed_dtls_writable_states = parsed_log.dtls_writable_states();
661 ASSERT_EQ(parsed_dtls_writable_states.size(),
662 dtls_writable_state_list_.size());
663 for (size_t i = 0; i < parsed_dtls_writable_states.size(); i++) {
664 verifier_.VerifyLoggedDtlsWritableState(*dtls_writable_state_list_[i],
665 parsed_dtls_writable_states[i]);
666 }
667
668 const auto& parsed_frame_decoded_map = parsed_log.decoded_frames();
669 ASSERT_EQ(parsed_frame_decoded_map.size(), frame_decoded_event_map_.size());
670 for (const auto& kv : parsed_frame_decoded_map) {
671 uint32_t ssrc = kv.first;
672 const auto& parsed_decoded_frames = kv.second;
673 const auto& decoded_frames = frame_decoded_event_map_[ssrc];
674 ASSERT_EQ(parsed_decoded_frames.size(), decoded_frames.size());
675 for (size_t i = 0; i < decoded_frames.size(); i++) {
676 verifier_.VerifyLoggedFrameDecoded(*decoded_frames[i],
677 parsed_decoded_frames[i]);
678 }
679 }
680
681 auto& parsed_ice_candidate_pair_configs =
682 parsed_log.ice_candidate_pair_configs();
683 ASSERT_EQ(parsed_ice_candidate_pair_configs.size(), ice_config_list_.size());
684 for (size_t i = 0; i < parsed_ice_candidate_pair_configs.size(); i++) {
685 verifier_.VerifyLoggedIceCandidatePairConfig(
686 *ice_config_list_[i], parsed_ice_candidate_pair_configs[i]);
687 }
688
689 auto& parsed_ice_candidate_pair_events =
690 parsed_log.ice_candidate_pair_events();
691 ASSERT_EQ(parsed_ice_candidate_pair_events.size(),
692 parsed_ice_candidate_pair_events.size());
693 for (size_t i = 0; i < parsed_ice_candidate_pair_events.size(); i++) {
694 verifier_.VerifyLoggedIceCandidatePairEvent(
695 *ice_event_list_[i], parsed_ice_candidate_pair_events[i]);
696 }
697
698 auto& parsed_incoming_rtp_packets_by_ssrc =
699 parsed_log.incoming_rtp_packets_by_ssrc();
700 ASSERT_EQ(parsed_incoming_rtp_packets_by_ssrc.size(),
701 incoming_rtp_map_.size());
702 for (const auto& kv : parsed_incoming_rtp_packets_by_ssrc) {
703 uint32_t ssrc = kv.ssrc;
704 const auto& parsed_rtp_stream = kv.incoming_packets;
705 const auto& rtp_stream = incoming_rtp_map_[ssrc];
706 ASSERT_EQ(parsed_rtp_stream.size(), rtp_stream.size());
707 for (size_t i = 0; i < parsed_rtp_stream.size(); i++) {
708 verifier_.VerifyLoggedRtpPacketIncoming(*rtp_stream[i],
709 parsed_rtp_stream[i]);
710 }
711 }
712
713 auto& parsed_outgoing_rtp_packets_by_ssrc =
714 parsed_log.outgoing_rtp_packets_by_ssrc();
715 ASSERT_EQ(parsed_outgoing_rtp_packets_by_ssrc.size(),
716 outgoing_rtp_map_.size());
717 for (const auto& kv : parsed_outgoing_rtp_packets_by_ssrc) {
718 uint32_t ssrc = kv.ssrc;
719 const auto& parsed_rtp_stream = kv.outgoing_packets;
720 const auto& rtp_stream = outgoing_rtp_map_[ssrc];
721 ASSERT_EQ(parsed_rtp_stream.size(), rtp_stream.size());
722 for (size_t i = 0; i < parsed_rtp_stream.size(); i++) {
723 verifier_.VerifyLoggedRtpPacketOutgoing(*rtp_stream[i],
724 parsed_rtp_stream[i]);
725 }
726 }
727
728 auto& parsed_incoming_rtcp_packets = parsed_log.incoming_rtcp_packets();
729 ASSERT_EQ(parsed_incoming_rtcp_packets.size(), incoming_rtcp_list_.size());
730 for (size_t i = 0; i < parsed_incoming_rtcp_packets.size(); i++) {
731 verifier_.VerifyLoggedRtcpPacketIncoming(*incoming_rtcp_list_[i],
732 parsed_incoming_rtcp_packets[i]);
733 }
734
735 auto& parsed_outgoing_rtcp_packets = parsed_log.outgoing_rtcp_packets();
736 ASSERT_EQ(parsed_outgoing_rtcp_packets.size(), outgoing_rtcp_list_.size());
737 for (size_t i = 0; i < parsed_outgoing_rtcp_packets.size(); i++) {
738 verifier_.VerifyLoggedRtcpPacketOutgoing(*outgoing_rtcp_list_[i],
739 parsed_outgoing_rtcp_packets[i]);
740 }
741 auto& parsed_audio_recv_configs = parsed_log.audio_recv_configs();
742 ASSERT_EQ(parsed_audio_recv_configs.size(), audio_recv_config_list_.size());
743 for (size_t i = 0; i < parsed_audio_recv_configs.size(); i++) {
744 verifier_.VerifyLoggedAudioRecvConfig(*audio_recv_config_list_[i],
745 parsed_audio_recv_configs[i]);
746 }
747 auto& parsed_audio_send_configs = parsed_log.audio_send_configs();
748 ASSERT_EQ(parsed_audio_send_configs.size(), audio_send_config_list_.size());
749 for (size_t i = 0; i < parsed_audio_send_configs.size(); i++) {
750 verifier_.VerifyLoggedAudioSendConfig(*audio_send_config_list_[i],
751 parsed_audio_send_configs[i]);
752 }
753 auto& parsed_video_recv_configs = parsed_log.video_recv_configs();
754 ASSERT_EQ(parsed_video_recv_configs.size(), video_recv_config_list_.size());
755 for (size_t i = 0; i < parsed_video_recv_configs.size(); i++) {
756 verifier_.VerifyLoggedVideoRecvConfig(*video_recv_config_list_[i],
757 parsed_video_recv_configs[i]);
758 }
759 auto& parsed_video_send_configs = parsed_log.video_send_configs();
760 ASSERT_EQ(parsed_video_send_configs.size(), video_send_config_list_.size());
761 for (size_t i = 0; i < parsed_video_send_configs.size(); i++) {
762 verifier_.VerifyLoggedVideoSendConfig(*video_send_config_list_[i],
763 parsed_video_send_configs[i]);
764 }
765
766 auto& parsed_generic_packets_received = parsed_log.generic_packets_received();
767 ASSERT_EQ(parsed_generic_packets_received.size(),
768 generic_packets_received_.size());
769 for (size_t i = 0; i < parsed_generic_packets_received.size(); i++) {
770 verifier_.VerifyLoggedGenericPacketReceived(
771 *generic_packets_received_[i], parsed_generic_packets_received[i]);
772 }
773
774 auto& parsed_generic_packets_sent = parsed_log.generic_packets_sent();
775 ASSERT_EQ(parsed_generic_packets_sent.size(), generic_packets_sent_.size());
776 for (size_t i = 0; i < parsed_generic_packets_sent.size(); i++) {
777 verifier_.VerifyLoggedGenericPacketSent(*generic_packets_sent_[i],
778 parsed_generic_packets_sent[i]);
779 }
780
781 auto& parsed_generic_acks_received = parsed_log.generic_acks_received();
782 ASSERT_EQ(parsed_generic_acks_received.size(), generic_acks_received_.size());
783 for (size_t i = 0; i < parsed_generic_acks_received.size(); i++) {
784 verifier_.VerifyLoggedGenericAckReceived(*generic_acks_received_[i],
785 parsed_generic_acks_received[i]);
786 }
787
788 EXPECT_EQ(first_timestamp_ms_, parsed_log.first_timestamp().ms());
789 EXPECT_EQ(last_timestamp_ms_, parsed_log.last_timestamp().ms());
790
791 EXPECT_EQ(parsed_log.first_log_segment().start_time_ms(),
792 std::min(start_time_us_ / 1000, first_timestamp_ms_));
793 EXPECT_EQ(parsed_log.first_log_segment().stop_time_ms(),
794 stop_time_us_ / 1000);
795 }
796
797 } // namespace
798
TEST_P(RtcEventLogSession,StartLoggingFromBeginning)799 TEST_P(RtcEventLogSession, StartLoggingFromBeginning) {
800 EventCounts count;
801 count.audio_send_streams = 2;
802 count.audio_recv_streams = 2;
803 count.video_send_streams = 3;
804 count.video_recv_streams = 4;
805 count.alr_states = 4;
806 count.audio_playouts = 100;
807 count.ana_configs = 3;
808 count.bwe_loss_events = 20;
809 count.bwe_delay_events = 20;
810 count.probe_creations = 4;
811 count.probe_successes = 2;
812 count.probe_failures = 2;
813 count.ice_configs = 3;
814 count.ice_events = 10;
815 count.incoming_rtp_packets = 100;
816 count.outgoing_rtp_packets = 100;
817 count.incoming_rtcp_packets = 20;
818 count.outgoing_rtcp_packets = 20;
819 if (IsNewFormat()) {
820 count.dtls_transport_states = 4;
821 count.dtls_writable_states = 2;
822 count.frame_decoded_events = 50;
823 count.generic_packets_sent = 100;
824 count.generic_packets_received = 100;
825 count.generic_acks_received = 20;
826 count.route_changes = 4;
827 }
828
829 WriteLog(count, 0);
830 ReadAndVerifyLog();
831 }
832
TEST_P(RtcEventLogSession,StartLoggingInTheMiddle)833 TEST_P(RtcEventLogSession, StartLoggingInTheMiddle) {
834 EventCounts count;
835 count.audio_send_streams = 3;
836 count.audio_recv_streams = 4;
837 count.video_send_streams = 5;
838 count.video_recv_streams = 6;
839 count.alr_states = 10;
840 count.audio_playouts = 500;
841 count.ana_configs = 10;
842 count.bwe_loss_events = 50;
843 count.bwe_delay_events = 50;
844 count.probe_creations = 10;
845 count.probe_successes = 5;
846 count.probe_failures = 5;
847 count.ice_configs = 10;
848 count.ice_events = 20;
849 count.incoming_rtp_packets = 500;
850 count.outgoing_rtp_packets = 500;
851 count.incoming_rtcp_packets = 50;
852 count.outgoing_rtcp_packets = 50;
853 if (IsNewFormat()) {
854 count.dtls_transport_states = 4;
855 count.dtls_writable_states = 5;
856 count.frame_decoded_events = 250;
857 count.generic_packets_sent = 500;
858 count.generic_packets_received = 500;
859 count.generic_acks_received = 50;
860 count.route_changes = 10;
861 }
862
863 WriteLog(count, 500);
864 ReadAndVerifyLog();
865 }
866
867 INSTANTIATE_TEST_SUITE_P(
868 RtcEventLogTest,
869 RtcEventLogSession,
870 ::testing::Combine(
871 ::testing::Values(1234567, 7654321),
872 ::testing::Values(RtcEventLog::kImmediateOutput, 1, 5),
873 ::testing::Values(RtcEventLog::EncodingType::Legacy,
874 RtcEventLog::EncodingType::NewFormat)));
875
876 class RtcEventLogCircularBufferTest
877 : public ::testing::TestWithParam<RtcEventLog::EncodingType> {
878 public:
RtcEventLogCircularBufferTest()879 RtcEventLogCircularBufferTest()
880 : encoding_type_(GetParam()),
881 verifier_(encoding_type_),
882 log_storage_(),
883 log_output_factory_(log_storage_.CreateFactory()) {}
884 const RtcEventLog::EncodingType encoding_type_;
885 const test::EventVerifier verifier_;
886 MemoryLogStorage log_storage_;
887 std::unique_ptr<LogWriterFactoryInterface> log_output_factory_;
888 };
889
TEST_P(RtcEventLogCircularBufferTest,KeepsMostRecentEvents)890 TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
891 // TODO(terelius): Maybe make a separate RtcEventLogImplTest that can access
892 // the size of the cyclic buffer?
893 constexpr size_t kNumEvents = 20000;
894 constexpr int64_t kStartTimeSeconds = 1;
895 constexpr int32_t kStartBitrate = 1000000;
896
897 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
898 std::string test_name =
899 std::string(test_info->test_case_name()) + "_" + test_info->name();
900 std::replace(test_name.begin(), test_name.end(), '/', '_');
901 const std::string temp_filename = test::OutputPath() + test_name;
902
903 std::unique_ptr<rtc::ScopedFakeClock> fake_clock =
904 std::make_unique<rtc::ScopedFakeClock>();
905 fake_clock->SetTime(Timestamp::Seconds(kStartTimeSeconds));
906
907 // Create a scope for the TQ and event log factories.
908 // This way, we make sure that task queue instances that may rely on a clock
909 // have been torn down before we run the verification steps at the end of
910 // the test.
911 int64_t start_time_us, utc_start_time_us, stop_time_us;
912
913 {
914 auto task_queue_factory = CreateDefaultTaskQueueFactory();
915 RtcEventLogFactory rtc_event_log_factory(task_queue_factory.get());
916 // When `log` goes out of scope, the contents are flushed
917 // to the output.
918 std::unique_ptr<RtcEventLog> log =
919 rtc_event_log_factory.CreateRtcEventLog(encoding_type_);
920
921 for (size_t i = 0; i < kNumEvents; i++) {
922 // The purpose of the test is to verify that the log can handle
923 // more events than what fits in the internal circular buffer. The exact
924 // type of events does not matter so we chose ProbeSuccess events for
925 // simplicity.
926 // We base the various values on the index. We use this for some basic
927 // consistency checks when we read back.
928 log->Log(std::make_unique<RtcEventProbeResultSuccess>(
929 i, kStartBitrate + i * 1000));
930 fake_clock->AdvanceTime(TimeDelta::Millis(10));
931 }
932 start_time_us = rtc::TimeMicros();
933 utc_start_time_us = rtc::TimeUTCMicros();
934 log->StartLogging(log_output_factory_->Create(temp_filename),
935 RtcEventLog::kImmediateOutput);
936 fake_clock->AdvanceTime(TimeDelta::Millis(10));
937 stop_time_us = rtc::TimeMicros();
938 log->StopLogging();
939 }
940
941 // Read the generated log from memory.
942 ParsedRtcEventLog parsed_log;
943 auto it = log_storage_.logs().find(temp_filename);
944 ASSERT_TRUE(it != log_storage_.logs().end());
945 ASSERT_TRUE(parsed_log.ParseString(it->second).ok());
946
947 const auto& start_log_events = parsed_log.start_log_events();
948 ASSERT_EQ(start_log_events.size(), 1u);
949 verifier_.VerifyLoggedStartEvent(start_time_us, utc_start_time_us,
950 start_log_events[0]);
951
952 const auto& stop_log_events = parsed_log.stop_log_events();
953 ASSERT_EQ(stop_log_events.size(), 1u);
954 verifier_.VerifyLoggedStopEvent(stop_time_us, stop_log_events[0]);
955
956 const auto& probe_success_events = parsed_log.bwe_probe_success_events();
957 // If the following fails, it probably means that kNumEvents isn't larger
958 // than the size of the cyclic buffer in the event log. Try increasing
959 // kNumEvents.
960 EXPECT_LT(probe_success_events.size(), kNumEvents);
961
962 ASSERT_GT(probe_success_events.size(), 1u);
963 int64_t first_timestamp_ms = probe_success_events[0].timestamp.ms();
964 uint32_t first_id = probe_success_events[0].id;
965 int32_t first_bitrate_bps = probe_success_events[0].bitrate_bps;
966 // We want to reset the time to what we used when generating the events, but
967 // the fake clock implementation DCHECKS if time moves backwards. We therefore
968 // recreate the clock. However we must ensure that the old fake_clock is
969 // destroyed before the new one is created, so we have to reset() first.
970 fake_clock.reset();
971 fake_clock = std::make_unique<rtc::ScopedFakeClock>();
972 fake_clock->SetTime(Timestamp::Millis(first_timestamp_ms));
973 for (size_t i = 1; i < probe_success_events.size(); i++) {
974 fake_clock->AdvanceTime(TimeDelta::Millis(10));
975 verifier_.VerifyLoggedBweProbeSuccessEvent(
976 RtcEventProbeResultSuccess(first_id + i, first_bitrate_bps + i * 1000),
977 probe_success_events[i]);
978 }
979 }
980
981 INSTANTIATE_TEST_SUITE_P(
982 RtcEventLogTest,
983 RtcEventLogCircularBufferTest,
984 ::testing::Values(RtcEventLog::EncodingType::Legacy,
985 RtcEventLog::EncodingType::NewFormat));
986
987 // TODO(terelius): Verify parser behavior if the timestamps are not
988 // monotonically increasing in the log.
989
TEST(DereferencingVectorTest,NonConstVector)990 TEST(DereferencingVectorTest, NonConstVector) {
991 std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
992 DereferencingVector<int> even;
993 EXPECT_TRUE(even.empty());
994 EXPECT_EQ(even.size(), 0u);
995 EXPECT_EQ(even.begin(), even.end());
996 for (size_t i = 0; i < v.size(); i += 2) {
997 even.push_back(&v[i]);
998 }
999 EXPECT_FALSE(even.empty());
1000 EXPECT_EQ(even.size(), 5u);
1001 EXPECT_NE(even.begin(), even.end());
1002
1003 // Test direct access.
1004 for (size_t i = 0; i < even.size(); i++) {
1005 EXPECT_EQ(even[i], 2 * static_cast<int>(i));
1006 }
1007
1008 // Test iterator.
1009 for (int val : even) {
1010 EXPECT_EQ(val % 2, 0);
1011 }
1012
1013 // Test modification through iterator.
1014 for (int& val : even) {
1015 val = val * 2;
1016 EXPECT_EQ(val % 2, 0);
1017 }
1018
1019 // Backing vector should have been modified.
1020 std::vector<int> expected{0, 1, 4, 3, 8, 5, 12, 7, 16, 9};
1021 for (size_t i = 0; i < v.size(); i++) {
1022 EXPECT_EQ(v[i], expected[i]);
1023 }
1024 }
1025
TEST(DereferencingVectorTest,ConstVector)1026 TEST(DereferencingVectorTest, ConstVector) {
1027 std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1028 DereferencingVector<const int> odd;
1029 EXPECT_TRUE(odd.empty());
1030 EXPECT_EQ(odd.size(), 0u);
1031 EXPECT_EQ(odd.begin(), odd.end());
1032 for (size_t i = 1; i < v.size(); i += 2) {
1033 odd.push_back(&v[i]);
1034 }
1035 EXPECT_FALSE(odd.empty());
1036 EXPECT_EQ(odd.size(), 5u);
1037 EXPECT_NE(odd.begin(), odd.end());
1038
1039 // Test direct access.
1040 for (size_t i = 0; i < odd.size(); i++) {
1041 EXPECT_EQ(odd[i], 2 * static_cast<int>(i) + 1);
1042 }
1043
1044 // Test iterator.
1045 for (int val : odd) {
1046 EXPECT_EQ(val % 2, 1);
1047 }
1048 }
1049
1050 } // namespace webrtc
1051