/*
 *  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 "logging/rtc_event_log/rtc_event_log_unittest_helper.h"

#include <string.h>  // memcmp

#include <limits>
#include <memory>
#include <numeric>
#include <utility>
#include <vector>

#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/checks.h"

namespace webrtc {

namespace test {

namespace {

struct ExtensionPair {
  RTPExtensionType type;
  const char* name;
};

constexpr int kMaxCsrcs = 3;

// Maximum serialized size of a header extension, including 1 byte ID.
constexpr int kMaxExtensionSizeBytes = 4;
constexpr int kMaxNumExtensions = 5;

constexpr ExtensionPair kExtensions[kMaxNumExtensions] = {
    {RTPExtensionType::kRtpExtensionTransmissionTimeOffset,
     RtpExtension::kTimestampOffsetUri},
    {RTPExtensionType::kRtpExtensionAbsoluteSendTime,
     RtpExtension::kAbsSendTimeUri},
    {RTPExtensionType::kRtpExtensionTransportSequenceNumber,
     RtpExtension::kTransportSequenceNumberUri},
    {RTPExtensionType::kRtpExtensionAudioLevel, RtpExtension::kAudioLevelUri},
    {RTPExtensionType::kRtpExtensionVideoRotation,
     RtpExtension::kVideoRotationUri}};

template <typename T>
void ShuffleInPlace(Random* prng, rtc::ArrayView<T> array) {
  RTC_DCHECK_LE(array.size(), std::numeric_limits<uint32_t>::max());
  for (uint32_t i = 0; i + 1 < array.size(); i++) {
    uint32_t other = prng->Rand(i, static_cast<uint32_t>(array.size() - 1));
    std::swap(array[i], array[other]);
  }
}
}  // namespace

std::unique_ptr<RtcEventAlrState> EventGenerator::NewAlrState() {
  return rtc::MakeUnique<RtcEventAlrState>(prng_.Rand<bool>());
}

std::unique_ptr<RtcEventAudioPlayout> EventGenerator::NewAudioPlayout(
    uint32_t ssrc) {
  return rtc::MakeUnique<RtcEventAudioPlayout>(ssrc);
}

std::unique_ptr<RtcEventAudioNetworkAdaptation>
EventGenerator::NewAudioNetworkAdaptation() {
  std::unique_ptr<AudioEncoderRuntimeConfig> config =
      rtc::MakeUnique<AudioEncoderRuntimeConfig>();

  config->bitrate_bps = prng_.Rand(0, 3000000);
  config->enable_fec = prng_.Rand<bool>();
  config->enable_dtx = prng_.Rand<bool>();
  config->frame_length_ms = prng_.Rand(10, 120);
  config->num_channels = prng_.Rand(1, 2);
  config->uplink_packet_loss_fraction = prng_.Rand<float>();

  return rtc::MakeUnique<RtcEventAudioNetworkAdaptation>(std::move(config));
}

std::unique_ptr<RtcEventBweUpdateDelayBased>
EventGenerator::NewBweUpdateDelayBased() {
  constexpr int32_t kMaxBweBps = 20000000;
  int32_t bitrate_bps = prng_.Rand(0, kMaxBweBps);
  BandwidthUsage state = static_cast<BandwidthUsage>(
      prng_.Rand(static_cast<uint32_t>(BandwidthUsage::kLast) - 1));
  return rtc::MakeUnique<RtcEventBweUpdateDelayBased>(bitrate_bps, state);
}

std::unique_ptr<RtcEventBweUpdateLossBased>
EventGenerator::NewBweUpdateLossBased() {
  constexpr int32_t kMaxBweBps = 20000000;
  constexpr int32_t kMaxPackets = 1000;
  int32_t bitrate_bps = prng_.Rand(0, kMaxBweBps);
  uint8_t fraction_lost = prng_.Rand<uint8_t>();
  int32_t total_packets = prng_.Rand(1, kMaxPackets);

  return rtc::MakeUnique<RtcEventBweUpdateLossBased>(bitrate_bps, fraction_lost,
                                                     total_packets);
}

std::unique_ptr<RtcEventProbeClusterCreated>
EventGenerator::NewProbeClusterCreated() {
  constexpr int kMaxBweBps = 20000000;
  constexpr int kMaxNumProbes = 10000;
  int id = prng_.Rand(1, kMaxNumProbes);
  int bitrate_bps = prng_.Rand(0, kMaxBweBps);
  int min_probes = prng_.Rand(5, 50);
  int min_bytes = prng_.Rand(500, 50000);

  return rtc::MakeUnique<RtcEventProbeClusterCreated>(id, bitrate_bps,
                                                      min_probes, min_bytes);
}

std::unique_ptr<RtcEventProbeResultFailure>
EventGenerator::NewProbeResultFailure() {
  constexpr int kMaxNumProbes = 10000;
  int id = prng_.Rand(1, kMaxNumProbes);
  ProbeFailureReason reason = static_cast<ProbeFailureReason>(
      prng_.Rand(static_cast<uint32_t>(ProbeFailureReason::kLast) - 1));

  return rtc::MakeUnique<RtcEventProbeResultFailure>(id, reason);
}

std::unique_ptr<RtcEventProbeResultSuccess>
EventGenerator::NewProbeResultSuccess() {
  constexpr int kMaxBweBps = 20000000;
  constexpr int kMaxNumProbes = 10000;
  int id = prng_.Rand(1, kMaxNumProbes);
  int bitrate_bps = prng_.Rand(0, kMaxBweBps);

  return rtc::MakeUnique<RtcEventProbeResultSuccess>(id, bitrate_bps);
}

std::unique_ptr<RtcEventIceCandidatePairConfig>
EventGenerator::NewIceCandidatePairConfig() {
  IceCandidateType local_candidate_type = static_cast<IceCandidateType>(
      prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1));
  IceCandidateNetworkType local_network_type =
      static_cast<IceCandidateNetworkType>(prng_.Rand(
          static_cast<uint32_t>(IceCandidateNetworkType::kNumValues) - 1));
  IceCandidatePairAddressFamily local_address_family =
      static_cast<IceCandidatePairAddressFamily>(prng_.Rand(
          static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) -
          1));
  IceCandidateType remote_candidate_type = static_cast<IceCandidateType>(
      prng_.Rand(static_cast<uint32_t>(IceCandidateType::kNumValues) - 1));
  IceCandidatePairAddressFamily remote_address_family =
      static_cast<IceCandidatePairAddressFamily>(prng_.Rand(
          static_cast<uint32_t>(IceCandidatePairAddressFamily::kNumValues) -
          1));
  IceCandidatePairProtocol protocol_type =
      static_cast<IceCandidatePairProtocol>(prng_.Rand(
          static_cast<uint32_t>(IceCandidatePairProtocol::kNumValues) - 1));

  IceCandidatePairDescription desc;
  desc.local_candidate_type = local_candidate_type;
  desc.local_relay_protocol = protocol_type;
  desc.local_network_type = local_network_type;
  desc.local_address_family = local_address_family;
  desc.remote_candidate_type = remote_candidate_type;
  desc.remote_address_family = remote_address_family;
  desc.candidate_pair_protocol = protocol_type;

  IceCandidatePairConfigType type =
      static_cast<IceCandidatePairConfigType>(prng_.Rand(
          static_cast<uint32_t>(IceCandidatePairConfigType::kNumValues) - 1));
  uint32_t pair_id = prng_.Rand<uint32_t>();
  return rtc::MakeUnique<RtcEventIceCandidatePairConfig>(type, pair_id, desc);
}

std::unique_ptr<RtcEventIceCandidatePair>
EventGenerator::NewIceCandidatePair() {
  IceCandidatePairEventType type =
      static_cast<IceCandidatePairEventType>(prng_.Rand(
          static_cast<uint32_t>(IceCandidatePairEventType::kNumValues) - 1));
  uint32_t pair_id = prng_.Rand<uint32_t>();

  return rtc::MakeUnique<RtcEventIceCandidatePair>(type, pair_id);
}

rtcp::ReportBlock EventGenerator::NewReportBlock() {
  rtcp::ReportBlock report_block;
  report_block.SetMediaSsrc(prng_.Rand<uint32_t>());
  report_block.SetFractionLost(prng_.Rand<uint8_t>());
  // cumulative_lost is a 3-byte signed value.
  RTC_DCHECK(report_block.SetCumulativeLost(
      prng_.Rand(-(1 << 23) + 1, (1 << 23) - 1)));
  report_block.SetExtHighestSeqNum(prng_.Rand<uint32_t>());
  report_block.SetJitter(prng_.Rand<uint32_t>());
  report_block.SetLastSr(prng_.Rand<uint32_t>());
  report_block.SetDelayLastSr(prng_.Rand<uint32_t>());
  return report_block;
}

rtcp::SenderReport EventGenerator::NewSenderReport() {
  rtcp::SenderReport sender_report;
  sender_report.SetSenderSsrc(prng_.Rand<uint32_t>());
  sender_report.SetNtp(NtpTime(prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>()));
  sender_report.SetPacketCount(prng_.Rand<uint32_t>());
  sender_report.AddReportBlock(NewReportBlock());
  return sender_report;
}

rtcp::ReceiverReport EventGenerator::NewReceiverReport() {
  rtcp::ReceiverReport receiver_report;
  receiver_report.SetSenderSsrc(prng_.Rand<uint32_t>());
  receiver_report.AddReportBlock(NewReportBlock());
  return receiver_report;
}

std::unique_ptr<RtcEventRtcpPacketIncoming>
EventGenerator::NewRtcpPacketIncoming() {
  // TODO(terelius): Test the other RTCP types too.
  switch (prng_.Rand(0, 1)) {
    case 0: {
      rtcp::SenderReport sender_report = NewSenderReport();
      rtc::Buffer buffer = sender_report.Build();
      return rtc::MakeUnique<RtcEventRtcpPacketIncoming>(buffer);
    }
    case 1: {
      rtcp::ReceiverReport receiver_report = NewReceiverReport();
      rtc::Buffer buffer = receiver_report.Build();
      return rtc::MakeUnique<RtcEventRtcpPacketIncoming>(buffer);
    }
    default:
      RTC_NOTREACHED();
  }
}

std::unique_ptr<RtcEventRtcpPacketOutgoing>
EventGenerator::NewRtcpPacketOutgoing() {
  // TODO(terelius): Test the other RTCP types too.
  switch (prng_.Rand(0, 1)) {
    case 0: {
      rtcp::SenderReport sender_report = NewSenderReport();
      rtc::Buffer buffer = sender_report.Build();
      return rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(buffer);
    }
    case 1: {
      rtcp::ReceiverReport receiver_report = NewReceiverReport();
      rtc::Buffer buffer = receiver_report.Build();
      return rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(buffer);
    }
    default:
      RTC_NOTREACHED();
  }
}

void EventGenerator::RandomizeRtpPacket(
    size_t packet_size,
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extension_map,
    RtpPacket* rtp_packet) {
  constexpr int kMaxPayloadType = 127;
  rtp_packet->SetPayloadType(prng_.Rand(kMaxPayloadType));
  rtp_packet->SetMarker(prng_.Rand<bool>());
  rtp_packet->SetSequenceNumber(prng_.Rand<uint16_t>());
  rtp_packet->SetSsrc(ssrc);
  rtp_packet->SetTimestamp(prng_.Rand<uint32_t>());

  uint32_t csrcs_count = prng_.Rand(0, kMaxCsrcs);
  std::vector<uint32_t> csrcs;
  for (size_t i = 0; i < csrcs_count; i++) {
    csrcs.push_back(prng_.Rand<uint32_t>());
  }
  rtp_packet->SetCsrcs(csrcs);

  if (extension_map.IsRegistered(TransmissionOffset::kId))
    rtp_packet->SetExtension<TransmissionOffset>(prng_.Rand(0x00ffffff));
  if (extension_map.IsRegistered(AudioLevel::kId))
    rtp_packet->SetExtension<AudioLevel>(prng_.Rand<bool>(), prng_.Rand(127));
  if (extension_map.IsRegistered(AbsoluteSendTime::kId))
    rtp_packet->SetExtension<AbsoluteSendTime>(prng_.Rand(0x00ffffff));
  if (extension_map.IsRegistered(VideoOrientation::kId))
    rtp_packet->SetExtension<VideoOrientation>(prng_.Rand(3));
  if (extension_map.IsRegistered(TransportSequenceNumber::kId))
    rtp_packet->SetExtension<TransportSequenceNumber>(prng_.Rand<uint16_t>());

  RTC_DCHECK_GE(packet_size, rtp_packet->headers_size());
  size_t payload_size = packet_size - rtp_packet->headers_size();
  RTC_CHECK_LE(rtp_packet->headers_size() + payload_size, IP_PACKET_SIZE);
  uint8_t* payload = rtp_packet->AllocatePayload(payload_size);
  RTC_DCHECK(payload != nullptr);
  for (size_t i = 0; i < payload_size; i++) {
    payload[i] = prng_.Rand<uint8_t>();
  }
}

std::unique_ptr<RtcEventRtpPacketIncoming> EventGenerator::NewRtpPacketIncoming(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extension_map) {
  // 12 bytes RTP header, 4 bytes for 0xBEDE + alignment, 4 bytes per CSRC.
  constexpr size_t kMaxHeaderSize =
      16 + 4 * kMaxCsrcs + kMaxExtensionSizeBytes * kMaxNumExtensions;
  size_t packet_size =
      prng_.Rand(kMaxHeaderSize, static_cast<uint32_t>(IP_PACKET_SIZE - 1));

  RtpPacketReceived rtp_packet(&extension_map);
  RandomizeRtpPacket(packet_size, ssrc, extension_map, &rtp_packet);

  return rtc::MakeUnique<RtcEventRtpPacketIncoming>(rtp_packet);
}

std::unique_ptr<RtcEventRtpPacketOutgoing> EventGenerator::NewRtpPacketOutgoing(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extension_map) {
  // 12 bytes RTP header, 4 bytes for 0xBEDE + alignment, 4 bytes per CSRC.
  constexpr size_t kMaxHeaderSize =
      16 + 4 * kMaxCsrcs + kMaxExtensionSizeBytes * kMaxNumExtensions;
  size_t packet_size =
      prng_.Rand(kMaxHeaderSize, static_cast<uint32_t>(IP_PACKET_SIZE - 1));

  RtpPacketToSend rtp_packet(&extension_map, packet_size);
  RandomizeRtpPacket(packet_size, ssrc, extension_map, &rtp_packet);

  int probe_cluster_id = prng_.Rand(0, 100000);
  return rtc::MakeUnique<RtcEventRtpPacketOutgoing>(rtp_packet,
                                                    probe_cluster_id);
}

RtpHeaderExtensionMap EventGenerator::NewRtpHeaderExtensionMap() {
  RtpHeaderExtensionMap extension_map;
  std::vector<int> id(RtpExtension::kMaxId - RtpExtension::kMinId + 1);
  std::iota(id.begin(), id.end(), RtpExtension::kMinId);
  ShuffleInPlace(&prng_, rtc::ArrayView<int>(id));

  if (prng_.Rand<bool>()) {
    extension_map.Register<AudioLevel>(id[0]);
  }
  if (prng_.Rand<bool>()) {
    extension_map.Register<TransmissionOffset>(id[1]);
  }
  if (prng_.Rand<bool>()) {
    extension_map.Register<AbsoluteSendTime>(id[2]);
  }
  if (prng_.Rand<bool>()) {
    extension_map.Register<VideoOrientation>(id[3]);
  }
  if (prng_.Rand<bool>()) {
    extension_map.Register<TransportSequenceNumber>(id[4]);
  }

  return extension_map;
}

std::unique_ptr<RtcEventAudioReceiveStreamConfig>
EventGenerator::NewAudioReceiveStreamConfig(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extensions) {
  auto config = rtc::MakeUnique<rtclog::StreamConfig>();
  // Add SSRCs for the stream.
  config->remote_ssrc = ssrc;
  config->local_ssrc = prng_.Rand<uint32_t>();
  // Add header extensions.
  for (size_t i = 0; i < kMaxNumExtensions; i++) {
    uint8_t id = extensions.GetId(kExtensions[i].type);
    if (id != RtpHeaderExtensionMap::kInvalidId) {
      config->rtp_extensions.emplace_back(kExtensions[i].name, id);
    }
  }

  return rtc::MakeUnique<RtcEventAudioReceiveStreamConfig>(std::move(config));
}

std::unique_ptr<RtcEventAudioSendStreamConfig>
EventGenerator::NewAudioSendStreamConfig(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extensions) {
  auto config = rtc::MakeUnique<rtclog::StreamConfig>();
  // Add SSRC to the stream.
  config->local_ssrc = ssrc;
  // Add header extensions.
  for (size_t i = 0; i < kMaxNumExtensions; i++) {
    uint8_t id = extensions.GetId(kExtensions[i].type);
    if (id != RtpHeaderExtensionMap::kInvalidId) {
      config->rtp_extensions.emplace_back(kExtensions[i].name, id);
    }
  }
  return rtc::MakeUnique<RtcEventAudioSendStreamConfig>(std::move(config));
}

std::unique_ptr<RtcEventVideoReceiveStreamConfig>
EventGenerator::NewVideoReceiveStreamConfig(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extensions) {
  auto config = rtc::MakeUnique<rtclog::StreamConfig>();

  // Add SSRCs for the stream.
  config->remote_ssrc = ssrc;
  config->local_ssrc = prng_.Rand<uint32_t>();
  // Add extensions and settings for RTCP.
  config->rtcp_mode =
      prng_.Rand<bool>() ? RtcpMode::kCompound : RtcpMode::kReducedSize;
  config->remb = prng_.Rand<bool>();
  config->rtx_ssrc = prng_.Rand<uint32_t>();
  config->codecs.emplace_back(prng_.Rand<bool>() ? "VP8" : "H264",
                              prng_.Rand(127), prng_.Rand(127));
  // Add header extensions.
  for (size_t i = 0; i < kMaxNumExtensions; i++) {
    uint8_t id = extensions.GetId(kExtensions[i].type);
    if (id != RtpHeaderExtensionMap::kInvalidId) {
      config->rtp_extensions.emplace_back(kExtensions[i].name, id);
    }
  }
  return rtc::MakeUnique<RtcEventVideoReceiveStreamConfig>(std::move(config));
}

std::unique_ptr<RtcEventVideoSendStreamConfig>
EventGenerator::NewVideoSendStreamConfig(
    uint32_t ssrc,
    const RtpHeaderExtensionMap& extensions) {
  auto config = rtc::MakeUnique<rtclog::StreamConfig>();

  config->codecs.emplace_back(prng_.Rand<bool>() ? "VP8" : "H264",
                              prng_.Rand(127), prng_.Rand(127));
  config->local_ssrc = ssrc;
  config->rtx_ssrc = prng_.Rand<uint32_t>();
  // Add header extensions.
  for (size_t i = 0; i < kMaxNumExtensions; i++) {
    uint8_t id = extensions.GetId(kExtensions[i].type);
    if (id != RtpHeaderExtensionMap::kInvalidId) {
      config->rtp_extensions.emplace_back(kExtensions[i].name, id);
    }
  }
  return rtc::MakeUnique<RtcEventVideoSendStreamConfig>(std::move(config));
}

bool VerifyLoggedAlrStateEvent(const RtcEventAlrState& original_event,
                               const LoggedAlrStateEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.in_alr_ != logged_event.in_alr)
    return false;
  return true;
}

bool VerifyLoggedAudioPlayoutEvent(
    const RtcEventAudioPlayout& original_event,
    const LoggedAudioPlayoutEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.ssrc_ != logged_event.ssrc)
    return false;
  return true;
}

bool VerifyLoggedAudioNetworkAdaptationEvent(
    const RtcEventAudioNetworkAdaptation& original_event,
    const LoggedAudioNetworkAdaptationEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.config_->bitrate_bps != logged_event.config.bitrate_bps)
    return false;
  if (original_event.config_->enable_dtx != logged_event.config.enable_dtx)
    return false;
  if (original_event.config_->enable_fec != logged_event.config.enable_fec)
    return false;
  if (original_event.config_->frame_length_ms !=
      logged_event.config.frame_length_ms)
    return false;
  if (original_event.config_->num_channels != logged_event.config.num_channels)
    return false;
  if (original_event.config_->uplink_packet_loss_fraction !=
      logged_event.config.uplink_packet_loss_fraction)
    return false;

  return true;
}

bool VerifyLoggedBweDelayBasedUpdate(
    const RtcEventBweUpdateDelayBased& original_event,
    const LoggedBweDelayBasedUpdate& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.bitrate_bps_ != logged_event.bitrate_bps)
    return false;
  if (original_event.detector_state_ != logged_event.detector_state)
    return false;
  return true;
}

bool VerifyLoggedBweLossBasedUpdate(
    const RtcEventBweUpdateLossBased& original_event,
    const LoggedBweLossBasedUpdate& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.bitrate_bps_ != logged_event.bitrate_bps)
    return false;
  if (original_event.fraction_loss_ != logged_event.fraction_lost)
    return false;
  if (original_event.total_packets_ != logged_event.expected_packets)
    return false;
  return true;
}

bool VerifyLoggedBweProbeClusterCreatedEvent(
    const RtcEventProbeClusterCreated& original_event,
    const LoggedBweProbeClusterCreatedEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.id_ != logged_event.id)
    return false;
  if (original_event.bitrate_bps_ != logged_event.bitrate_bps)
    return false;
  if (original_event.min_probes_ != logged_event.min_packets)
    return false;
  if (original_event.min_bytes_ != logged_event.min_bytes)
    return false;

  return true;
}

bool VerifyLoggedBweProbeFailureEvent(
    const RtcEventProbeResultFailure& original_event,
    const LoggedBweProbeFailureEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.id_ != logged_event.id)
    return false;
  if (original_event.failure_reason_ != logged_event.failure_reason)
    return false;
  return true;
}

bool VerifyLoggedBweProbeSuccessEvent(
    const RtcEventProbeResultSuccess& original_event,
    const LoggedBweProbeSuccessEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (original_event.id_ != logged_event.id)
    return false;
  if (original_event.bitrate_bps_ != logged_event.bitrate_bps)
    return false;
  return true;
}

bool VerifyLoggedIceCandidatePairConfig(
    const RtcEventIceCandidatePairConfig& original_event,
    const LoggedIceCandidatePairConfig& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.type_ != logged_event.type)
    return false;
  if (original_event.candidate_pair_id_ != logged_event.candidate_pair_id)
    return false;
  if (original_event.candidate_pair_desc_.local_candidate_type !=
      logged_event.local_candidate_type)
    return false;
  if (original_event.candidate_pair_desc_.local_relay_protocol !=
      logged_event.local_relay_protocol)
    return false;
  if (original_event.candidate_pair_desc_.local_network_type !=
      logged_event.local_network_type)
    return false;
  if (original_event.candidate_pair_desc_.local_address_family !=
      logged_event.local_address_family)
    return false;
  if (original_event.candidate_pair_desc_.remote_candidate_type !=
      logged_event.remote_candidate_type)
    return false;
  if (original_event.candidate_pair_desc_.remote_address_family !=
      logged_event.remote_address_family)
    return false;
  if (original_event.candidate_pair_desc_.candidate_pair_protocol !=
      logged_event.candidate_pair_protocol)
    return false;

  return true;
}

bool VerifyLoggedIceCandidatePairEvent(
    const RtcEventIceCandidatePair& original_event,
    const LoggedIceCandidatePairEvent& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.type_ != logged_event.type)
    return false;
  if (original_event.candidate_pair_id_ != logged_event.candidate_pair_id)
    return false;

  return true;
}

bool VerifyLoggedRtpHeader(const RtpPacket& original_header,
                           const RTPHeader& logged_header) {
  // Standard RTP header.
  if (original_header.Marker() != logged_header.markerBit)
    return false;
  if (original_header.PayloadType() != logged_header.payloadType)
    return false;
  if (original_header.SequenceNumber() != logged_header.sequenceNumber)
    return false;
  if (original_header.Timestamp() != logged_header.timestamp)
    return false;
  if (original_header.Ssrc() != logged_header.ssrc)
    return false;
  if (original_header.Csrcs().size() != logged_header.numCSRCs)
    return false;
  for (size_t i = 0; i < logged_header.numCSRCs; i++) {
    if (original_header.Csrcs()[i] != logged_header.arrOfCSRCs[i])
      return false;
  }

  if (original_header.padding_size() != logged_header.paddingLength)
    return false;
  if (original_header.headers_size() != logged_header.headerLength)
    return false;

  // TransmissionOffset header extension.
  if (original_header.HasExtension<TransmissionOffset>() !=
      logged_header.extension.hasTransmissionTimeOffset)
    return false;
  if (logged_header.extension.hasTransmissionTimeOffset) {
    int32_t offset;
    original_header.GetExtension<TransmissionOffset>(&offset);
    if (offset != logged_header.extension.transmissionTimeOffset)
      return false;
  }

  // AbsoluteSendTime header extension.
  if (original_header.HasExtension<AbsoluteSendTime>() !=
      logged_header.extension.hasAbsoluteSendTime)
    return false;
  if (logged_header.extension.hasAbsoluteSendTime) {
    uint32_t sendtime;
    original_header.GetExtension<AbsoluteSendTime>(&sendtime);
    if (sendtime != logged_header.extension.absoluteSendTime)
      return false;
  }

  // TransportSequenceNumber header extension.
  if (original_header.HasExtension<TransportSequenceNumber>() !=
      logged_header.extension.hasTransportSequenceNumber)
    return false;
  if (logged_header.extension.hasTransportSequenceNumber) {
    uint16_t seqnum;
    original_header.GetExtension<TransportSequenceNumber>(&seqnum);
    if (seqnum != logged_header.extension.transportSequenceNumber)
      return false;
  }

  // AudioLevel header extension.
  if (original_header.HasExtension<AudioLevel>() !=
      logged_header.extension.hasAudioLevel)
    return false;
  if (logged_header.extension.hasAudioLevel) {
    bool voice_activity;
    uint8_t audio_level;
    original_header.GetExtension<AudioLevel>(&voice_activity, &audio_level);
    if (voice_activity != logged_header.extension.voiceActivity)
      return false;
    if (audio_level != logged_header.extension.audioLevel)
      return false;
  }

  // VideoOrientation header extension.
  if (original_header.HasExtension<VideoOrientation>() !=
      logged_header.extension.hasVideoRotation)
    return false;
  if (logged_header.extension.hasVideoRotation) {
    uint8_t rotation;
    original_header.GetExtension<VideoOrientation>(&rotation);
    if (ConvertCVOByteToVideoRotation(rotation) !=
        logged_header.extension.videoRotation)
      return false;
  }

  return true;
}

bool VerifyLoggedRtpPacketIncoming(
    const RtcEventRtpPacketIncoming& original_event,
    const LoggedRtpPacketIncoming& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.header_.headers_size() != logged_event.rtp.header_length)
    return false;

  if (original_event.packet_length_ != logged_event.rtp.total_length)
    return false;

  if (!VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header))
    return false;

  return true;
}

bool VerifyLoggedRtpPacketOutgoing(
    const RtcEventRtpPacketOutgoing& original_event,
    const LoggedRtpPacketOutgoing& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.header_.headers_size() != logged_event.rtp.header_length)
    return false;

  if (original_event.packet_length_ != logged_event.rtp.total_length)
    return false;

  // TODO(terelius): Probe cluster ID isn't parsed, used or tested. Unless
  // someone has a strong reason to keep it, it'll be removed.

  if (!VerifyLoggedRtpHeader(original_event.header_, logged_event.rtp.header))
    return false;

  return true;
}

bool VerifyLoggedRtcpPacketIncoming(
    const RtcEventRtcpPacketIncoming& original_event,
    const LoggedRtcpPacketIncoming& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.packet_.size() != logged_event.rtcp.raw_data.size())
    return false;
  if (memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(),
             original_event.packet_.size()) != 0) {
    return false;
  }
  return true;
}

bool VerifyLoggedRtcpPacketOutgoing(
    const RtcEventRtcpPacketOutgoing& original_event,
    const LoggedRtcpPacketOutgoing& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;

  if (original_event.packet_.size() != logged_event.rtcp.raw_data.size())
    return false;
  if (memcmp(original_event.packet_.data(), logged_event.rtcp.raw_data.data(),
             original_event.packet_.size()) != 0) {
    return false;
  }
  return true;
}

bool VerifyLoggedStartEvent(int64_t start_time_us,
                            const LoggedStartEvent& logged_event) {
  if (start_time_us != logged_event.log_time_us())
    return false;
  return true;
}

bool VerifyLoggedStopEvent(int64_t stop_time_us,
                           const LoggedStopEvent& logged_event) {
  if (stop_time_us != logged_event.log_time_us())
    return false;
  return true;
}

bool VerifyLoggedAudioRecvConfig(
    const RtcEventAudioReceiveStreamConfig& original_event,
    const LoggedAudioRecvConfig& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (*original_event.config_ != logged_event.config)
    return false;
  return true;
}

bool VerifyLoggedAudioSendConfig(
    const RtcEventAudioSendStreamConfig& original_event,
    const LoggedAudioSendConfig& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (*original_event.config_ != logged_event.config)
    return false;
  return true;
}

bool VerifyLoggedVideoRecvConfig(
    const RtcEventVideoReceiveStreamConfig& original_event,
    const LoggedVideoRecvConfig& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  if (*original_event.config_ != logged_event.config)
    return false;
  return true;
}

bool VerifyLoggedVideoSendConfig(
    const RtcEventVideoSendStreamConfig& original_event,
    const LoggedVideoSendConfig& logged_event) {
  if (original_event.timestamp_us_ != logged_event.log_time_us())
    return false;
  // TODO(terelius): In the past, we allowed storing multiple RtcStreamConfigs
  // in the same RtcEventVideoSendStreamConfig. Look into whether we should drop
  // backwards compatibility in the parser.
  if (logged_event.configs.size() != 1)
    return false;
  if (*original_event.config_ != logged_event.configs[0])
    return false;
  return true;
}

}  // namespace test
}  // namespace webrtc
