/*
 *  Copyright (c) 2015 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/modules/rtp_rtcp/source/rtcp_packet/dlrr.h"

#include "testing/gtest/include/gtest/gtest.h"

#include "webrtc/modules/rtp_rtcp/source/byte_io.h"

using webrtc::rtcp::Dlrr;

namespace webrtc {
namespace {

const uint32_t kSsrc = 0x12345678;
const uint32_t kLastRR = 0x23344556;
const uint32_t kDelay = 0x33343536;
const uint8_t kBlock[] = {0x05, 0x00, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
                          0x23, 0x34, 0x45, 0x56, 0x33, 0x34, 0x35, 0x36};
const size_t kBlockSizeBytes = sizeof(kBlock);

TEST(RtcpPacketDlrrTest, Empty) {
  Dlrr dlrr;

  EXPECT_EQ(0u, dlrr.BlockLength());
}

TEST(RtcpPacketDlrrTest, Create) {
  Dlrr dlrr;
  EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay));

  ASSERT_EQ(kBlockSizeBytes, dlrr.BlockLength());
  uint8_t buffer[kBlockSizeBytes];

  dlrr.Create(buffer);
  EXPECT_EQ(0, memcmp(buffer, kBlock, kBlockSizeBytes));
}

TEST(RtcpPacketDlrrTest, Parse) {
  Dlrr dlrr;
  uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&kBlock[2]);
  EXPECT_TRUE(dlrr.Parse(kBlock, block_length));

  EXPECT_EQ(1u, dlrr.sub_blocks().size());
  const Dlrr::SubBlock& block = dlrr.sub_blocks().front();
  EXPECT_EQ(kSsrc, block.ssrc);
  EXPECT_EQ(kLastRR, block.last_rr);
  EXPECT_EQ(kDelay, block.delay_since_last_rr);
}

TEST(RtcpPacketDlrrTest, ParseFailsOnBadSize) {
  const size_t kBigBufferSize = 0x100;  // More than enough.
  uint8_t buffer[kBigBufferSize];
  buffer[0] = Dlrr::kBlockType;
  buffer[1] = 0;  // Reserved.
  buffer[2] = 0;  // Most significant size byte.
  for (uint8_t size = 3; size < 6; ++size) {
    buffer[3] = size;
    Dlrr dlrr;
    // Parse should be successful only when size is multiple of 3.
    EXPECT_EQ(size % 3 == 0, dlrr.Parse(buffer, static_cast<uint16_t>(size)));
  }
}

TEST(RtcpPacketDlrrTest, FailsOnTooManySubBlocks) {
  Dlrr dlrr;
  for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) {
    EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i));
  }
  EXPECT_FALSE(dlrr.WithDlrrItem(kSsrc, kLastRR, kDelay));
}

TEST(RtcpPacketDlrrTest, CreateAndParseMaxSubBlocks) {
  const size_t kBufferSize = 0x1000;  // More than enough.
  uint8_t buffer[kBufferSize];

  // Create.
  Dlrr dlrr;
  for (size_t i = 1; i <= Dlrr::kMaxNumberOfDlrrItems; ++i) {
    EXPECT_TRUE(dlrr.WithDlrrItem(kSsrc + i, kLastRR + i, kDelay + i));
  }
  size_t used_buffer_size = dlrr.BlockLength();
  ASSERT_LE(used_buffer_size, kBufferSize);
  dlrr.Create(buffer);

  // Parse.
  Dlrr parsed;
  uint16_t block_length = ByteReader<uint16_t>::ReadBigEndian(&buffer[2]);
  EXPECT_EQ(used_buffer_size, (block_length + 1) * 4u);
  EXPECT_TRUE(parsed.Parse(buffer, block_length));
  EXPECT_TRUE(parsed.sub_blocks().size() == Dlrr::kMaxNumberOfDlrrItems);
}

}  // namespace
}  // namespace webrtc
