nack_unittest.cc (5698B)
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 "modules/rtp_rtcp/source/rtcp_packet/nack.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <iterator> 16 17 #include "api/array_view.h" 18 #include "rtc_base/buffer.h" 19 #include "test/gmock.h" 20 #include "test/gtest.h" 21 #include "test/rtcp_packet_parser.h" 22 23 namespace webrtc { 24 namespace { 25 26 using rtcp::Nack; 27 using ::testing::_; 28 using ::testing::ElementsAre; 29 using ::testing::ElementsAreArray; 30 using ::testing::Invoke; 31 using ::testing::make_tuple; 32 using ::testing::MockFunction; 33 using ::testing::UnorderedElementsAreArray; 34 35 constexpr uint32_t kSenderSsrc = 0x12345678; 36 constexpr uint32_t kRemoteSsrc = 0x23456789; 37 38 constexpr uint8_t kRtpVersionBits = 2 << 6; 39 constexpr uint16_t kList[] = {0, 1, 3, 8, 16}; 40 // clang-format off 41 constexpr uint8_t kPacket[] = { 42 kRtpVersionBits | Nack::kFeedbackMessageType, Nack::kPacketType, 0, 3, 43 0x12, 0x34, 0x56, 0x78, 44 0x23, 0x45, 0x67, 0x89, 45 0x00, 0x00, 0x80, 0x85}; 46 47 constexpr uint16_t kWrapList[] = {0xffdc, 0xffec, 0xfffe, 0xffff, 0x0000, 48 0x0001, 0x0003, 0x0014, 0x0064}; 49 constexpr size_t kWrapListLength = sizeof(kWrapList) / sizeof(kWrapList[0]); 50 constexpr uint8_t kWrapPacket[] = { 51 kRtpVersionBits | Nack::kFeedbackMessageType, Nack::kPacketType, 0, 6, 52 0x12, 0x34, 0x56, 0x78, 53 0x23, 0x45, 0x67, 0x89, 54 0xff, 0xdc, 0x80, 0x00, 55 0xff, 0xfe, 0x00, 0x17, 56 0x00, 0x14, 0x00, 0x00, 57 0x00, 0x64, 0x00, 0x00}; 58 constexpr uint8_t kTooSmallPacket[] = { 59 kRtpVersionBits | Nack::kFeedbackMessageType, Nack::kPacketType, 0, 2, 60 0x12, 0x34, 0x56, 0x78, 61 0x23, 0x45, 0x67, 0x89}; 62 // clang-format on 63 } // namespace 64 65 TEST(RtcpPacketNackTest, Create) { 66 Nack nack; 67 nack.SetSenderSsrc(kSenderSsrc); 68 nack.SetMediaSsrc(kRemoteSsrc); 69 nack.SetPacketIds(kList, std::size(kList)); 70 71 Buffer packet = nack.Build(); 72 73 EXPECT_THAT(make_tuple(packet.data(), packet.size()), 74 ElementsAreArray(kPacket)); 75 } 76 77 TEST(RtcpPacketNackTest, Parse) { 78 Nack parsed; 79 EXPECT_TRUE(test::ParseSinglePacket(kPacket, &parsed)); 80 const Nack& const_parsed = parsed; 81 82 EXPECT_EQ(kSenderSsrc, const_parsed.sender_ssrc()); 83 EXPECT_EQ(kRemoteSsrc, const_parsed.media_ssrc()); 84 EXPECT_THAT(const_parsed.packet_ids(), ElementsAreArray(kList)); 85 } 86 87 TEST(RtcpPacketNackTest, CreateWrap) { 88 Nack nack; 89 nack.SetSenderSsrc(kSenderSsrc); 90 nack.SetMediaSsrc(kRemoteSsrc); 91 nack.SetPacketIds(kWrapList, kWrapListLength); 92 93 Buffer packet = nack.Build(); 94 95 EXPECT_THAT(make_tuple(packet.data(), packet.size()), 96 ElementsAreArray(kWrapPacket)); 97 } 98 99 TEST(RtcpPacketNackTest, ParseWrap) { 100 Nack parsed; 101 EXPECT_TRUE(test::ParseSinglePacket(kWrapPacket, &parsed)); 102 103 EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); 104 EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); 105 EXPECT_THAT(parsed.packet_ids(), ElementsAreArray(kWrapList)); 106 } 107 108 TEST(RtcpPacketNackTest, BadOrder) { 109 // Does not guarantee optimal packing, but should guarantee correctness. 110 const uint16_t kUnorderedList[] = {1, 25, 13, 12, 9, 27, 29}; 111 const size_t kUnorderedListLength = 112 sizeof(kUnorderedList) / sizeof(kUnorderedList[0]); 113 Nack nack; 114 nack.SetSenderSsrc(kSenderSsrc); 115 nack.SetMediaSsrc(kRemoteSsrc); 116 nack.SetPacketIds(kUnorderedList, kUnorderedListLength); 117 118 Buffer packet = nack.Build(); 119 120 Nack parsed; 121 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed)); 122 123 EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc()); 124 EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc()); 125 EXPECT_THAT(parsed.packet_ids(), UnorderedElementsAreArray(kUnorderedList)); 126 } 127 128 TEST(RtcpPacketNackTest, CreateFragmented) { 129 Nack nack; 130 const uint16_t kFragmentedList[] = {1, 100, 200, 300, 400}; 131 nack.SetSenderSsrc(kSenderSsrc); 132 nack.SetMediaSsrc(kRemoteSsrc); 133 nack.SetPacketIds(kFragmentedList, std::size(kFragmentedList)); 134 135 const size_t kBufferSize = 12 + (3 * 4); // Fits common header + 3 nack items 136 137 MockFunction<void(ArrayView<const uint8_t>)> callback; 138 EXPECT_CALL(callback, Call(_)) 139 .WillOnce(Invoke([&](ArrayView<const uint8_t> packet) { 140 Nack nack; 141 EXPECT_TRUE(test::ParseSinglePacket(packet, &nack)); 142 EXPECT_EQ(kSenderSsrc, nack.sender_ssrc()); 143 EXPECT_EQ(kRemoteSsrc, nack.media_ssrc()); 144 EXPECT_THAT(nack.packet_ids(), ElementsAre(1, 100, 200)); 145 })) 146 .WillOnce(Invoke([&](ArrayView<const uint8_t> packet) { 147 Nack nack; 148 EXPECT_TRUE(test::ParseSinglePacket(packet, &nack)); 149 EXPECT_EQ(kSenderSsrc, nack.sender_ssrc()); 150 EXPECT_EQ(kRemoteSsrc, nack.media_ssrc()); 151 EXPECT_THAT(nack.packet_ids(), ElementsAre(300, 400)); 152 })); 153 154 EXPECT_TRUE(nack.Build(kBufferSize, callback.AsStdFunction())); 155 } 156 157 TEST(RtcpPacketNackTest, CreateFailsWithTooSmallBuffer) { 158 const uint16_t kSmallList[] = {1}; 159 const size_t kMinNackBlockSize = 16; 160 Nack nack; 161 nack.SetSenderSsrc(kSenderSsrc); 162 nack.SetMediaSsrc(kRemoteSsrc); 163 nack.SetPacketIds(kSmallList, std::size(kSmallList)); 164 165 MockFunction<void(ArrayView<const uint8_t>)> callback; 166 EXPECT_CALL(callback, Call(_)).Times(0); 167 EXPECT_FALSE(nack.Build(kMinNackBlockSize - 1, callback.AsStdFunction())); 168 } 169 170 TEST(RtcpPacketNackTest, ParseFailsWithTooSmallBuffer) { 171 Nack parsed; 172 EXPECT_FALSE(test::ParseSinglePacket(kTooSmallPacket, &parsed)); 173 } 174 175 } // namespace webrtc