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 "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h" 12 13#include "testing/gmock/include/gmock/gmock.h" 14#include "testing/gtest/include/gtest/gtest.h" 15 16using ::testing::_; 17using ::testing::ElementsAreArray; 18using ::testing::Invoke; 19using ::testing::UnorderedElementsAreArray; 20 21using webrtc::rtcp::Nack; 22using webrtc::rtcp::RawPacket; 23using webrtc::RTCPUtility::RtcpCommonHeader; 24using webrtc::RTCPUtility::RtcpParseCommonHeader; 25 26namespace webrtc { 27namespace { 28 29const uint32_t kSenderSsrc = 0x12345678; 30const uint32_t kRemoteSsrc = 0x23456789; 31 32const uint16_t kList[] = {0, 1, 3, 8, 16}; 33const size_t kListLength = sizeof(kList) / sizeof(kList[0]); 34const uint8_t kPacket[] = {0x81, 205, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, 35 0x23, 0x45, 0x67, 0x89, 0x00, 0x00, 0x80, 0x85}; 36const size_t kPacketLength = sizeof(kPacket); 37 38const uint16_t kWrapList[] = {0xffdc, 0xffec, 0xfffe, 0xffff, 0x0000, 39 0x0001, 0x0003, 0x0014, 0x0064}; 40const size_t kWrapListLength = sizeof(kWrapList) / sizeof(kWrapList[0]); 41const uint8_t kWrapPacket[] = {0x81, 205, 0x00, 0x06, 0x12, 0x34, 0x56, 0x78, 42 0x23, 0x45, 0x67, 0x89, 0xff, 0xdc, 0x80, 0x00, 43 0xff, 0xfe, 0x00, 0x17, 0x00, 0x14, 0x00, 0x00, 44 0x00, 0x64, 0x00, 0x00}; 45const size_t kWrapPacketLength = sizeof(kWrapPacket); 46 47TEST(RtcpPacketNackTest, Create) { 48 Nack nack; 49 nack.From(kSenderSsrc); 50 nack.To(kRemoteSsrc); 51 nack.WithList(kList, kListLength); 52 53 rtc::scoped_ptr<RawPacket> packet = nack.Build(); 54 55 EXPECT_EQ(kPacketLength, packet->Length()); 56 EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength)); 57} 58 59TEST(RtcpPacketNackTest, Parse) { 60 RtcpCommonHeader header; 61 EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); 62 EXPECT_EQ(kPacketLength, header.BlockSize()); 63 Nack parsed; 64 65 EXPECT_TRUE( 66 parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); 67 const Nack& const_parsed = parsed; 68 69 EXPECT_EQ(kSenderSsrc, const_parsed.sender_ssrc()); 70 EXPECT_EQ(kRemoteSsrc, const_parsed.media_ssrc()); 71 EXPECT_THAT(const_parsed.packet_ids(), ElementsAreArray(kList)); 72} 73 74TEST(RtcpPacketNackTest, CreateWrap) { 75 Nack nack; 76 nack.From(kSenderSsrc); 77 nack.To(kRemoteSsrc); 78 nack.WithList(kWrapList, kWrapListLength); 79 80 rtc::scoped_ptr<RawPacket> packet = nack.Build(); 81 82 EXPECT_EQ(kWrapPacketLength, packet->Length()); 83 EXPECT_EQ(0, memcmp(kWrapPacket, packet->Buffer(), kWrapPacketLength)); 84} 85 86TEST(RtcpPacketNackTest, ParseWrap) { 87 RtcpCommonHeader header; 88 EXPECT_TRUE(RtcpParseCommonHeader(kWrapPacket, kWrapPacketLength, &header)); 89 EXPECT_EQ(kWrapPacketLength, header.BlockSize()); 90 91 Nack parsed; 92 EXPECT_TRUE( 93 parsed.Parse(header, kWrapPacket + RtcpCommonHeader::kHeaderSizeBytes)); 94 95 EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); 96 EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); 97 EXPECT_THAT(parsed.packet_ids(), ElementsAreArray(kWrapList)); 98} 99 100TEST(RtcpPacketNackTest, BadOrder) { 101 // Does not guarantee optimal packing, but should guarantee correctness. 102 const uint16_t kUnorderedList[] = {1, 25, 13, 12, 9, 27, 29}; 103 const size_t kUnorderedListLength = 104 sizeof(kUnorderedList) / sizeof(kUnorderedList[0]); 105 Nack nack; 106 nack.From(kSenderSsrc); 107 nack.To(kRemoteSsrc); 108 nack.WithList(kUnorderedList, kUnorderedListLength); 109 110 rtc::scoped_ptr<RawPacket> packet = nack.Build(); 111 112 Nack parsed; 113 RtcpCommonHeader header; 114 EXPECT_TRUE( 115 RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header)); 116 EXPECT_TRUE(parsed.Parse( 117 header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes)); 118 119 EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); 120 EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); 121 EXPECT_THAT(parsed.packet_ids(), UnorderedElementsAreArray(kUnorderedList)); 122} 123 124TEST(RtcpPacketNackTest, CreateFragmented) { 125 Nack nack; 126 const uint16_t kList[] = {1, 100, 200, 300, 400}; 127 const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]); 128 nack.From(kSenderSsrc); 129 nack.To(kRemoteSsrc); 130 nack.WithList(kList, kListLength); 131 132 class MockPacketReadyCallback : public rtcp::RtcpPacket::PacketReadyCallback { 133 public: 134 MOCK_METHOD2(OnPacketReady, void(uint8_t*, size_t)); 135 } verifier; 136 137 class NackVerifier { 138 public: 139 explicit NackVerifier(std::vector<uint16_t> ids) : ids_(ids) {} 140 void operator()(uint8_t* data, size_t length) { 141 RtcpCommonHeader header; 142 EXPECT_TRUE(RtcpParseCommonHeader(data, length, &header)); 143 EXPECT_EQ(length, header.BlockSize()); 144 Nack nack; 145 EXPECT_TRUE( 146 nack.Parse(header, data + RtcpCommonHeader::kHeaderSizeBytes)); 147 EXPECT_EQ(kSenderSsrc, nack.sender_ssrc()); 148 EXPECT_EQ(kRemoteSsrc, nack.media_ssrc()); 149 EXPECT_THAT(nack.packet_ids(), ElementsAreArray(ids_)); 150 } 151 std::vector<uint16_t> ids_; 152 } packet1({1, 100, 200}), packet2({300, 400}); 153 154 EXPECT_CALL(verifier, OnPacketReady(_, _)) 155 .WillOnce(Invoke(packet1)) 156 .WillOnce(Invoke(packet2)); 157 const size_t kBufferSize = 12 + (3 * 4); // Fits common header + 3 nack items 158 uint8_t buffer[kBufferSize]; 159 EXPECT_TRUE(nack.BuildExternalBuffer(buffer, kBufferSize, &verifier)); 160} 161 162TEST(RtcpPacketNackTest, CreateFailsWithTooSmallBuffer) { 163 const uint16_t kList[] = {1}; 164 const size_t kMinNackBlockSize = 16; 165 Nack nack; 166 nack.From(kSenderSsrc); 167 nack.To(kRemoteSsrc); 168 nack.WithList(kList, 1); 169 class Verifier : public rtcp::RtcpPacket::PacketReadyCallback { 170 public: 171 void OnPacketReady(uint8_t* data, size_t length) override { 172 ADD_FAILURE() << "Buffer should be too small."; 173 } 174 } verifier; 175 uint8_t buffer[kMinNackBlockSize - 1]; 176 EXPECT_FALSE( 177 nack.BuildExternalBuffer(buffer, kMinNackBlockSize - 1, &verifier)); 178} 179 180TEST(RtcpPacketNackTest, ParseFailsWithTooSmallBuffer) { 181 RtcpCommonHeader header; 182 EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header)); 183 header.payload_size_bytes--; // Damage the packet 184 Nack parsed; 185 EXPECT_FALSE( 186 parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes)); 187} 188 189} // namespace 190} // namespace webrtc 191