/* * Copyright (c) 2014 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 "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/checks.h" #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { using RTCPUtility::RtcpCommonHeader; namespace rtcp { TEST(RtcpUtilityTest, MidNtp) { const uint32_t kNtpSec = 0x12345678; const uint32_t kNtpFrac = 0x23456789; const uint32_t kNtpMid = 0x56782345; EXPECT_EQ(kNtpMid, RTCPUtility::MidNtp(kNtpSec, kNtpFrac)); } TEST(RtcpUtilityTest, NackRequests) { RTCPUtility::NackStats stats; EXPECT_EQ(0U, stats.unique_requests()); EXPECT_EQ(0U, stats.requests()); stats.ReportRequest(10); EXPECT_EQ(1U, stats.unique_requests()); EXPECT_EQ(1U, stats.requests()); stats.ReportRequest(10); EXPECT_EQ(1U, stats.unique_requests()); stats.ReportRequest(11); EXPECT_EQ(2U, stats.unique_requests()); stats.ReportRequest(11); EXPECT_EQ(2U, stats.unique_requests()); stats.ReportRequest(13); EXPECT_EQ(3U, stats.unique_requests()); stats.ReportRequest(11); EXPECT_EQ(3U, stats.unique_requests()); EXPECT_EQ(6U, stats.requests()); } TEST(RtcpUtilityTest, NackRequestsWithWrap) { RTCPUtility::NackStats stats; stats.ReportRequest(65534); EXPECT_EQ(1U, stats.unique_requests()); stats.ReportRequest(65534); EXPECT_EQ(1U, stats.unique_requests()); stats.ReportRequest(65535); EXPECT_EQ(2U, stats.unique_requests()); stats.ReportRequest(65535); EXPECT_EQ(2U, stats.unique_requests()); stats.ReportRequest(0); EXPECT_EQ(3U, stats.unique_requests()); stats.ReportRequest(65535); EXPECT_EQ(3U, stats.unique_requests()); stats.ReportRequest(0); EXPECT_EQ(3U, stats.unique_requests()); stats.ReportRequest(1); EXPECT_EQ(4U, stats.unique_requests()); EXPECT_EQ(8U, stats.requests()); } class RtcpParseCommonHeaderTest : public ::testing::Test { public: RtcpParseCommonHeaderTest() { memset(buffer, 0, kBufferCapacityBytes); } virtual ~RtcpParseCommonHeaderTest() {} protected: static const size_t kBufferCapacityBytes = 40; uint8_t buffer[kBufferCapacityBytes]; RtcpCommonHeader header; }; TEST_F(RtcpParseCommonHeaderTest, TooSmallBuffer) { // Buffer needs to be able to hold the header. for (size_t i = 0; i < RtcpCommonHeader::kHeaderSizeBytes; ++i) EXPECT_FALSE(RtcpParseCommonHeader(buffer, i, &header)); } TEST_F(RtcpParseCommonHeaderTest, Version) { // Version 2 is the only allowed for now. for (int v = 0; v < 4; ++v) { buffer[0] = v << 6; EXPECT_EQ(v == 2, RtcpParseCommonHeader( buffer, RtcpCommonHeader::kHeaderSizeBytes, &header)); } } TEST_F(RtcpParseCommonHeaderTest, PacketSize) { // Set v = 2, leave p, fmt, pt as 0. buffer[0] = 2 << 6; const size_t kBlockSize = 3; ByteWriter::WriteBigEndian(&buffer[2], kBlockSize); const size_t kSizeInBytes = (kBlockSize + 1) * 4; EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes - 1, &header)); EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); } TEST_F(RtcpParseCommonHeaderTest, PayloadSize) { // Set v = 2, p = 1, but leave fmt, pt as 0. buffer[0] = (2 << 6) | (1 << 5); // Padding bit set, but no byte for padding (can't specify padding length). EXPECT_FALSE(RtcpParseCommonHeader(buffer, 4, &header)); const size_t kBlockSize = 3; ByteWriter::WriteBigEndian(&buffer[2], kBlockSize); const size_t kSizeInBytes = (kBlockSize + 1) * 4; const size_t kPayloadSizeBytes = kSizeInBytes - RtcpCommonHeader::kHeaderSizeBytes; // Padding one byte larger than possible. buffer[kSizeInBytes - 1] = kPayloadSizeBytes + 1; EXPECT_FALSE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); // Pure padding packet? buffer[kSizeInBytes - 1] = kPayloadSizeBytes; EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); EXPECT_EQ(kPayloadSizeBytes, header.padding_bytes); EXPECT_EQ(0u, header.payload_size_bytes); // Single byte of actual data. buffer[kSizeInBytes - 1] = kPayloadSizeBytes - 1; EXPECT_TRUE(RtcpParseCommonHeader(buffer, kSizeInBytes, &header)); EXPECT_EQ(kPayloadSizeBytes - 1, header.padding_bytes); EXPECT_EQ(1u, header.payload_size_bytes); } TEST_F(RtcpParseCommonHeaderTest, FormatAndPayloadType) { // Format/count and packet type both set to max values. const uint8_t kCountOrFormat = 0x1F; const uint8_t kPacketType = 0xFF; buffer[0] = 2 << 6; // V = 2. buffer[0] |= kCountOrFormat; buffer[1] = kPacketType; EXPECT_TRUE(RtcpParseCommonHeader(buffer, RtcpCommonHeader::kHeaderSizeBytes, &header)); EXPECT_EQ(kCountOrFormat, header.count_or_format); EXPECT_EQ(kPacketType, header.packet_type); } } // namespace rtcp } // namespace webrtc