/*
 *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h"

#include <string.h>

#include <string>
#include <vector>

#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/test/gtest.h"
#include "webrtc/test/testsupport/fileutils.h"

// Files generated at build-time by the protobuf compiler.
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h"
#else
#include "webrtc/logging/rtc_event_log/rtc_event_log.pb.h"
#endif

namespace webrtc {

namespace {

BandwidthUsage GetRuntimeDetectorState(
    rtclog::DelayBasedBweUpdate::DetectorState detector_state) {
  switch (detector_state) {
    case rtclog::DelayBasedBweUpdate::BWE_NORMAL:
      return BandwidthUsage::kBwNormal;
    case rtclog::DelayBasedBweUpdate::BWE_UNDERUSING:
      return BandwidthUsage::kBwUnderusing;
    case rtclog::DelayBasedBweUpdate::BWE_OVERUSING:
      return BandwidthUsage::kBwOverusing;
  }
  RTC_NOTREACHED();
  return BandwidthUsage::kBwNormal;
}

rtclog::BweProbeResult::ResultType GetProbeResultType(
    ProbeFailureReason failure_reason) {
  switch (failure_reason) {
    case kInvalidSendReceiveInterval:
      return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_INTERVAL;
    case kInvalidSendReceiveRatio:
      return rtclog::BweProbeResult::INVALID_SEND_RECEIVE_RATIO;
    case kTimeout:
      return rtclog::BweProbeResult::TIMEOUT;
  }
  RTC_NOTREACHED();
  return rtclog::BweProbeResult::SUCCESS;
}
}  // namespace

// Checks that the event has a timestamp, a type and exactly the data field
// corresponding to the type.
::testing::AssertionResult IsValidBasicEvent(const rtclog::Event& event) {
  if (!event.has_timestamp_us()) {
    return ::testing::AssertionFailure() << "Event has no timestamp";
  }
  if (!event.has_type()) {
    return ::testing::AssertionFailure() << "Event has no event type";
  }
  rtclog::Event_EventType type = event.type();
  if ((type == rtclog::Event::RTP_EVENT) != event.has_rtp_packet()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_rtp_packet() ? "" : "no ") << "RTP packet";
  }
  if ((type == rtclog::Event::RTCP_EVENT) != event.has_rtcp_packet()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_rtcp_packet() ? "" : "no ") << "RTCP packet";
  }
  if ((type == rtclog::Event::LOSS_BASED_BWE_UPDATE) !=
      event.has_loss_based_bwe_update()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_loss_based_bwe_update() ? "" : "no ") << "loss update";
  }
  if ((type == rtclog::Event::DELAY_BASED_BWE_UPDATE) !=
      event.has_delay_based_bwe_update()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_delay_based_bwe_update() ? "" : "no ")
           << "delay update";
  }
  if ((type == rtclog::Event::AUDIO_PLAYOUT_EVENT) !=
      event.has_audio_playout_event()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_audio_playout_event() ? "" : "no ")
           << "audio_playout event";
  }
  if ((type == rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT) !=
      event.has_video_receiver_config()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_video_receiver_config() ? "" : "no ")
           << "receiver config";
  }
  if ((type == rtclog::Event::VIDEO_SENDER_CONFIG_EVENT) !=
      event.has_video_sender_config()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_video_sender_config() ? "" : "no ") << "sender config";
  }
  if ((type == rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT) !=
      event.has_audio_receiver_config()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_audio_receiver_config() ? "" : "no ")
           << "audio receiver config";
  }
  if ((type == rtclog::Event::AUDIO_SENDER_CONFIG_EVENT) !=
      event.has_audio_sender_config()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_audio_sender_config() ? "" : "no ")
           << "audio sender config";
  }
  if ((type == rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT) !=
      event.has_audio_network_adaptation()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_audio_network_adaptation() ? "" : "no ")
           << "audio network adaptation";
  }
  if ((type == rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT) !=
      event.has_probe_cluster()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_probe_cluster() ? "" : "no ") << "bwe probe cluster";
  }
  if ((type == rtclog::Event::BWE_PROBE_RESULT_EVENT) !=
      event.has_probe_result()) {
    return ::testing::AssertionFailure()
           << "Event of type " << type << " has "
           << (event.has_probe_result() ? "" : "no ") << "bwe probe result";
  }
  return ::testing::AssertionSuccess();
}

void VerifyStreamConfigsAreEqual(const rtclog::StreamConfig& config_1,
                                 const rtclog::StreamConfig& config_2) {
  EXPECT_EQ(config_1.remote_ssrc, config_2.remote_ssrc);
  EXPECT_EQ(config_1.local_ssrc, config_2.local_ssrc);
  EXPECT_EQ(config_1.rtx_ssrc, config_2.rtx_ssrc);
  EXPECT_EQ(config_1.rtcp_mode, config_2.rtcp_mode);
  EXPECT_EQ(config_1.remb, config_2.remb);

  ASSERT_EQ(config_1.rtp_extensions.size(), config_2.rtp_extensions.size());
  for (size_t i = 0; i < config_2.rtp_extensions.size(); i++) {
    EXPECT_EQ(config_1.rtp_extensions[i].uri, config_2.rtp_extensions[i].uri);
    EXPECT_EQ(config_1.rtp_extensions[i].id, config_2.rtp_extensions[i].id);
  }
  ASSERT_EQ(config_1.codecs.size(), config_2.codecs.size());
  for (size_t i = 0; i < config_2.codecs.size(); i++) {
    EXPECT_EQ(config_1.codecs[i].payload_name, config_2.codecs[i].payload_name);
    EXPECT_EQ(config_1.codecs[i].payload_type, config_2.codecs[i].payload_type);
    EXPECT_EQ(config_1.codecs[i].rtx_payload_type,
              config_2.codecs[i].rtx_payload_type);
  }
}

void RtcEventLogTestHelper::VerifyVideoReceiveStreamConfig(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    const rtclog::StreamConfig& config) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT, event.type());
  const rtclog::VideoReceiveConfig& receiver_config =
      event.video_receiver_config();
  // Check SSRCs.
  ASSERT_TRUE(receiver_config.has_remote_ssrc());
  EXPECT_EQ(config.remote_ssrc, receiver_config.remote_ssrc());
  ASSERT_TRUE(receiver_config.has_local_ssrc());
  EXPECT_EQ(config.local_ssrc, receiver_config.local_ssrc());
  // Check RTCP settings.
  ASSERT_TRUE(receiver_config.has_rtcp_mode());
  if (config.rtcp_mode == RtcpMode::kCompound) {
    EXPECT_EQ(rtclog::VideoReceiveConfig::RTCP_COMPOUND,
              receiver_config.rtcp_mode());
  } else {
    EXPECT_EQ(rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE,
              receiver_config.rtcp_mode());
  }
  ASSERT_TRUE(receiver_config.has_remb());
  EXPECT_EQ(config.remb, receiver_config.remb());
  // Check RTX map.
  for (const rtclog::RtxMap& rtx_map : receiver_config.rtx_map()) {
    ASSERT_TRUE(rtx_map.has_payload_type());
    ASSERT_TRUE(rtx_map.has_config());
    const rtclog::RtxConfig& rtx_config = rtx_map.config();
    ASSERT_TRUE(rtx_config.has_rtx_ssrc());
    ASSERT_TRUE(rtx_config.has_rtx_payload_type());

    EXPECT_EQ(config.rtx_ssrc, rtx_config.rtx_ssrc());
    auto codec_found =
        std::find_if(config.codecs.begin(), config.codecs.end(),
                     [&rtx_map](const rtclog::StreamConfig::Codec& codec) {
                       return rtx_map.payload_type() == codec.payload_type;
                     });
    ASSERT_TRUE(codec_found != config.codecs.end());
    EXPECT_EQ(rtx_config.rtx_payload_type(), codec_found->rtx_payload_type);
  }
  // Check header extensions.
  ASSERT_EQ(static_cast<int>(config.rtp_extensions.size()),
            receiver_config.header_extensions_size());
  for (int i = 0; i < receiver_config.header_extensions_size(); i++) {
    ASSERT_TRUE(receiver_config.header_extensions(i).has_name());
    ASSERT_TRUE(receiver_config.header_extensions(i).has_id());
    const std::string& name = receiver_config.header_extensions(i).name();
    int id = receiver_config.header_extensions(i).id();
    EXPECT_EQ(config.rtp_extensions[i].id, id);
    EXPECT_EQ(config.rtp_extensions[i].uri, name);
  }
  // Check decoders.
  ASSERT_EQ(static_cast<int>(config.codecs.size()),
            receiver_config.decoders_size());
  for (int i = 0; i < receiver_config.decoders_size(); i++) {
    ASSERT_TRUE(receiver_config.decoders(i).has_name());
    ASSERT_TRUE(receiver_config.decoders(i).has_payload_type());
    const std::string& decoder_name = receiver_config.decoders(i).name();
    int decoder_type = receiver_config.decoders(i).payload_type();
    EXPECT_EQ(config.codecs[i].payload_name, decoder_name);
    EXPECT_EQ(config.codecs[i].payload_type, decoder_type);
  }

  // Check consistency of the parser.
  rtclog::StreamConfig parsed_config = parsed_log.GetVideoReceiveConfig(index);
  VerifyStreamConfigsAreEqual(config, parsed_config);
}

void RtcEventLogTestHelper::VerifyVideoSendStreamConfig(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    const rtclog::StreamConfig& config) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::VIDEO_SENDER_CONFIG_EVENT, event.type());
  const rtclog::VideoSendConfig& sender_config = event.video_sender_config();

  EXPECT_EQ(config.local_ssrc, sender_config.ssrcs(0));
  EXPECT_EQ(config.rtx_ssrc, sender_config.rtx_ssrcs(0));

  // Check header extensions.
  ASSERT_EQ(static_cast<int>(config.rtp_extensions.size()),
            sender_config.header_extensions_size());
  for (int i = 0; i < sender_config.header_extensions_size(); i++) {
    ASSERT_TRUE(sender_config.header_extensions(i).has_name());
    ASSERT_TRUE(sender_config.header_extensions(i).has_id());
    const std::string& name = sender_config.header_extensions(i).name();
    int id = sender_config.header_extensions(i).id();
    EXPECT_EQ(config.rtp_extensions[i].id, id);
    EXPECT_EQ(config.rtp_extensions[i].uri, name);
  }
  // Check encoder.
  ASSERT_TRUE(sender_config.has_encoder());
  ASSERT_TRUE(sender_config.encoder().has_name());
  ASSERT_TRUE(sender_config.encoder().has_payload_type());
  EXPECT_EQ(config.codecs[0].payload_name, sender_config.encoder().name());
  EXPECT_EQ(config.codecs[0].payload_type,
            sender_config.encoder().payload_type());

  EXPECT_EQ(config.codecs[0].rtx_payload_type,
            sender_config.rtx_payload_type());

  // Check consistency of the parser.
  std::vector<rtclog::StreamConfig> parsed_configs =
      parsed_log.GetVideoSendConfig(index);
  ASSERT_EQ(1u, parsed_configs.size());
  VerifyStreamConfigsAreEqual(config, parsed_configs[0]);
}

void RtcEventLogTestHelper::VerifyAudioReceiveStreamConfig(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    const rtclog::StreamConfig& config) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::AUDIO_RECEIVER_CONFIG_EVENT, event.type());
  const rtclog::AudioReceiveConfig& receiver_config =
      event.audio_receiver_config();
  // Check SSRCs.
  ASSERT_TRUE(receiver_config.has_remote_ssrc());
  EXPECT_EQ(config.remote_ssrc, receiver_config.remote_ssrc());
  ASSERT_TRUE(receiver_config.has_local_ssrc());
  EXPECT_EQ(config.local_ssrc, receiver_config.local_ssrc());
  // Check header extensions.
  ASSERT_EQ(static_cast<int>(config.rtp_extensions.size()),
            receiver_config.header_extensions_size());
  for (int i = 0; i < receiver_config.header_extensions_size(); i++) {
    ASSERT_TRUE(receiver_config.header_extensions(i).has_name());
    ASSERT_TRUE(receiver_config.header_extensions(i).has_id());
    const std::string& name = receiver_config.header_extensions(i).name();
    int id = receiver_config.header_extensions(i).id();
    EXPECT_EQ(config.rtp_extensions[i].id, id);
    EXPECT_EQ(config.rtp_extensions[i].uri, name);
  }

  // Check consistency of the parser.
  rtclog::StreamConfig parsed_config = parsed_log.GetAudioReceiveConfig(index);
  EXPECT_EQ(config.remote_ssrc, parsed_config.remote_ssrc);
  EXPECT_EQ(config.local_ssrc, parsed_config.local_ssrc);
  // Check header extensions.
  EXPECT_EQ(config.rtp_extensions.size(), parsed_config.rtp_extensions.size());
  for (size_t i = 0; i < parsed_config.rtp_extensions.size(); i++) {
    EXPECT_EQ(config.rtp_extensions[i].uri,
              parsed_config.rtp_extensions[i].uri);
    EXPECT_EQ(config.rtp_extensions[i].id, parsed_config.rtp_extensions[i].id);
  }
}

void RtcEventLogTestHelper::VerifyAudioSendStreamConfig(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    const rtclog::StreamConfig& config) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::AUDIO_SENDER_CONFIG_EVENT, event.type());
  const rtclog::AudioSendConfig& sender_config = event.audio_sender_config();
  // Check SSRCs.
  EXPECT_EQ(config.local_ssrc, sender_config.ssrc());
  // Check header extensions.
  ASSERT_EQ(static_cast<int>(config.rtp_extensions.size()),
            sender_config.header_extensions_size());
  for (int i = 0; i < sender_config.header_extensions_size(); i++) {
    ASSERT_TRUE(sender_config.header_extensions(i).has_name());
    ASSERT_TRUE(sender_config.header_extensions(i).has_id());
    const std::string& name = sender_config.header_extensions(i).name();
    int id = sender_config.header_extensions(i).id();
    EXPECT_EQ(config.rtp_extensions[i].id, id);
    EXPECT_EQ(config.rtp_extensions[i].uri, name);
  }

  // Check consistency of the parser.
  rtclog::StreamConfig parsed_config = parsed_log.GetAudioSendConfig(index);
  VerifyStreamConfigsAreEqual(config, parsed_config);
}

void RtcEventLogTestHelper::VerifyRtpEvent(const ParsedRtcEventLog& parsed_log,
                                           size_t index,
                                           PacketDirection direction,
                                           const uint8_t* header,
                                           size_t header_size,
                                           size_t total_size) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::RTP_EVENT, event.type());
  const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
  ASSERT_TRUE(rtp_packet.has_incoming());
  EXPECT_EQ(direction == kIncomingPacket, rtp_packet.incoming());
  ASSERT_TRUE(rtp_packet.has_packet_length());
  EXPECT_EQ(total_size, rtp_packet.packet_length());
  ASSERT_TRUE(rtp_packet.has_header());
  ASSERT_EQ(header_size, rtp_packet.header().size());
  for (size_t i = 0; i < header_size; i++) {
    EXPECT_EQ(header[i], static_cast<uint8_t>(rtp_packet.header()[i]));
  }

  // Check consistency of the parser.
  PacketDirection parsed_direction;
  uint8_t parsed_header[1500];
  size_t parsed_header_size, parsed_total_size;
  parsed_log.GetRtpHeader(index, &parsed_direction, parsed_header,
                          &parsed_header_size, &parsed_total_size);
  EXPECT_EQ(direction, parsed_direction);
  ASSERT_EQ(header_size, parsed_header_size);
  EXPECT_EQ(0, std::memcmp(header, parsed_header, header_size));
  EXPECT_EQ(total_size, parsed_total_size);
}

void RtcEventLogTestHelper::VerifyRtcpEvent(const ParsedRtcEventLog& parsed_log,
                                            size_t index,
                                            PacketDirection direction,
                                            const uint8_t* packet,
                                            size_t total_size) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::RTCP_EVENT, event.type());
  const rtclog::RtcpPacket& rtcp_packet = event.rtcp_packet();
  ASSERT_TRUE(rtcp_packet.has_incoming());
  EXPECT_EQ(direction == kIncomingPacket, rtcp_packet.incoming());
  ASSERT_TRUE(rtcp_packet.has_packet_data());
  ASSERT_EQ(total_size, rtcp_packet.packet_data().size());
  for (size_t i = 0; i < total_size; i++) {
    EXPECT_EQ(packet[i], static_cast<uint8_t>(rtcp_packet.packet_data()[i]));
  }

  // Check consistency of the parser.
  PacketDirection parsed_direction;
  uint8_t parsed_packet[1500];
  size_t parsed_total_size;
  parsed_log.GetRtcpPacket(index, &parsed_direction, parsed_packet,
                           &parsed_total_size);
  EXPECT_EQ(direction, parsed_direction);
  ASSERT_EQ(total_size, parsed_total_size);
  EXPECT_EQ(0, std::memcmp(packet, parsed_packet, total_size));
}

void RtcEventLogTestHelper::VerifyPlayoutEvent(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    uint32_t ssrc) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::AUDIO_PLAYOUT_EVENT, event.type());
  const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
  ASSERT_TRUE(playout_event.has_local_ssrc());
  EXPECT_EQ(ssrc, playout_event.local_ssrc());

  // Check consistency of the parser.
  uint32_t parsed_ssrc;
  parsed_log.GetAudioPlayout(index, &parsed_ssrc);
  EXPECT_EQ(ssrc, parsed_ssrc);
}

void RtcEventLogTestHelper::VerifyBweLossEvent(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    int32_t bitrate,
    uint8_t fraction_loss,
    int32_t total_packets) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::LOSS_BASED_BWE_UPDATE, event.type());
  const rtclog::LossBasedBweUpdate& bwe_event = event.loss_based_bwe_update();
  ASSERT_TRUE(bwe_event.has_bitrate_bps());
  EXPECT_EQ(bitrate, bwe_event.bitrate_bps());
  ASSERT_TRUE(bwe_event.has_fraction_loss());
  EXPECT_EQ(fraction_loss, bwe_event.fraction_loss());
  ASSERT_TRUE(bwe_event.has_total_packets());
  EXPECT_EQ(total_packets, bwe_event.total_packets());

  // Check consistency of the parser.
  int32_t parsed_bitrate;
  uint8_t parsed_fraction_loss;
  int32_t parsed_total_packets;
  parsed_log.GetLossBasedBweUpdate(
      index, &parsed_bitrate, &parsed_fraction_loss, &parsed_total_packets);
  EXPECT_EQ(bitrate, parsed_bitrate);
  EXPECT_EQ(fraction_loss, parsed_fraction_loss);
  EXPECT_EQ(total_packets, parsed_total_packets);
}

void RtcEventLogTestHelper::VerifyBweDelayEvent(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    int32_t bitrate,
    BandwidthUsage detector_state) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  ASSERT_EQ(rtclog::Event::DELAY_BASED_BWE_UPDATE, event.type());
  const rtclog::DelayBasedBweUpdate& bwe_event = event.delay_based_bwe_update();
  ASSERT_TRUE(bwe_event.has_bitrate_bps());
  EXPECT_EQ(bitrate, bwe_event.bitrate_bps());
  ASSERT_TRUE(bwe_event.has_detector_state());
  EXPECT_EQ(detector_state,
            GetRuntimeDetectorState(bwe_event.detector_state()));

  // Check consistency of the parser.
  ParsedRtcEventLog::BweDelayBasedUpdate res =
      parsed_log.GetDelayBasedBweUpdate(index);
  EXPECT_EQ(res.bitrate_bps, bitrate);
  EXPECT_EQ(res.detector_state, detector_state);
}

void RtcEventLogTestHelper::VerifyAudioNetworkAdaptation(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    const AudioEncoderRuntimeConfig& config) {
  AudioEncoderRuntimeConfig parsed_config;
  parsed_log.GetAudioNetworkAdaptation(index, &parsed_config);
  EXPECT_EQ(config.bitrate_bps, parsed_config.bitrate_bps);
  EXPECT_EQ(config.enable_dtx, parsed_config.enable_dtx);
  EXPECT_EQ(config.enable_fec, parsed_config.enable_fec);
  EXPECT_EQ(config.frame_length_ms, parsed_config.frame_length_ms);
  EXPECT_EQ(config.num_channels, parsed_config.num_channels);
  EXPECT_EQ(config.uplink_packet_loss_fraction,
            parsed_config.uplink_packet_loss_fraction);
}

void RtcEventLogTestHelper::VerifyLogStartEvent(
    const ParsedRtcEventLog& parsed_log,
    size_t index) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  EXPECT_EQ(rtclog::Event::LOG_START, event.type());
}

void RtcEventLogTestHelper::VerifyLogEndEvent(
    const ParsedRtcEventLog& parsed_log,
    size_t index) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  EXPECT_EQ(rtclog::Event::LOG_END, event.type());
}

void RtcEventLogTestHelper::VerifyBweProbeCluster(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    uint32_t id,
    uint32_t bitrate_bps,
    uint32_t min_probes,
    uint32_t min_bytes) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  EXPECT_EQ(rtclog::Event::BWE_PROBE_CLUSTER_CREATED_EVENT, event.type());

  const rtclog::BweProbeCluster& bwe_event = event.probe_cluster();
  ASSERT_TRUE(bwe_event.has_id());
  EXPECT_EQ(id, bwe_event.id());
  ASSERT_TRUE(bwe_event.has_bitrate_bps());
  EXPECT_EQ(bitrate_bps, bwe_event.bitrate_bps());
  ASSERT_TRUE(bwe_event.has_min_packets());
  EXPECT_EQ(min_probes, bwe_event.min_packets());
  ASSERT_TRUE(bwe_event.has_min_bytes());
  EXPECT_EQ(min_bytes, bwe_event.min_bytes());

  // TODO(philipel): Verify the parser when parsing has been implemented.
}

void RtcEventLogTestHelper::VerifyProbeResultSuccess(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    uint32_t id,
    uint32_t bitrate_bps) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  EXPECT_EQ(rtclog::Event::BWE_PROBE_RESULT_EVENT, event.type());

  const rtclog::BweProbeResult& bwe_event = event.probe_result();
  ASSERT_TRUE(bwe_event.has_id());
  EXPECT_EQ(id, bwe_event.id());
  ASSERT_TRUE(bwe_event.has_bitrate_bps());
  EXPECT_EQ(bitrate_bps, bwe_event.bitrate_bps());
  ASSERT_TRUE(bwe_event.has_result());
  EXPECT_EQ(rtclog::BweProbeResult::SUCCESS, bwe_event.result());

  // TODO(philipel): Verify the parser when parsing has been implemented.
}

void RtcEventLogTestHelper::VerifyProbeResultFailure(
    const ParsedRtcEventLog& parsed_log,
    size_t index,
    uint32_t id,
    ProbeFailureReason failure_reason) {
  const rtclog::Event& event = parsed_log.events_[index];
  ASSERT_TRUE(IsValidBasicEvent(event));
  EXPECT_EQ(rtclog::Event::BWE_PROBE_RESULT_EVENT, event.type());

  const rtclog::BweProbeResult& bwe_event = event.probe_result();
  ASSERT_TRUE(bwe_event.has_id());
  EXPECT_EQ(id, bwe_event.id());
  ASSERT_TRUE(bwe_event.has_result());
  EXPECT_EQ(GetProbeResultType(failure_reason), bwe_event.result());
  ASSERT_FALSE(bwe_event.has_bitrate_bps());

  // TODO(philipel): Verify the parser when parsing has been implemented.
}

}  // namespace webrtc
