sdes_unittest.cc (8824B)
1 /* 2 * Copyright (c) 2016 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/sdes.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <string> 16 17 #include "rtc_base/buffer.h" 18 #include "rtc_base/strings/string_builder.h" 19 #include "test/gtest.h" 20 #include "test/rtcp_packet_parser.h" 21 22 using webrtc::rtcp::Sdes; 23 24 namespace webrtc { 25 namespace { 26 constexpr uint32_t kSenderSsrc = 0x12345678; 27 constexpr uint8_t kPadding = 0; 28 constexpr uint8_t kTerminatorTag = 0; 29 constexpr uint8_t kCnameTag = 1; 30 constexpr uint8_t kNameTag = 2; 31 constexpr uint8_t kEmailTag = 3; 32 } // namespace 33 34 TEST(RtcpPacketSdesTest, CreateAndParseWithoutChunks) { 35 Sdes sdes; 36 37 Buffer packet = sdes.Build(); 38 Sdes parsed; 39 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed)); 40 41 EXPECT_EQ(0u, parsed.chunks().size()); 42 } 43 44 TEST(RtcpPacketSdesTest, CreateAndParseWithOneChunk) { 45 const std::string kCname = "alice@host"; 46 47 Sdes sdes; 48 EXPECT_TRUE(sdes.AddCName(kSenderSsrc, kCname)); 49 50 Buffer packet = sdes.Build(); 51 Sdes sdes_parsed; 52 EXPECT_TRUE(test::ParseSinglePacket(packet, &sdes_parsed)); 53 const Sdes& parsed = sdes_parsed; // Ensure accessors are const. 54 55 EXPECT_EQ(1u, parsed.chunks().size()); 56 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); 57 EXPECT_EQ(kCname, parsed.chunks()[0].cname); 58 } 59 60 TEST(RtcpPacketSdesTest, CreateAndParseWithMultipleChunks) { 61 Sdes sdes; 62 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 0, "a")); 63 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 1, "ab")); 64 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 2, "abc")); 65 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 3, "abcd")); 66 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 4, "abcde")); 67 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 5, "abcdef")); 68 69 Buffer packet = sdes.Build(); 70 Sdes parsed; 71 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed)); 72 73 EXPECT_EQ(6u, parsed.chunks().size()); 74 EXPECT_EQ(kSenderSsrc + 5, parsed.chunks()[5].ssrc); 75 EXPECT_EQ("abcdef", parsed.chunks()[5].cname); 76 } 77 78 TEST(RtcpPacketSdesTest, CreateWithTooManyChunks) { 79 const size_t kMaxChunks = (1 << 5) - 1; 80 Sdes sdes; 81 for (size_t i = 0; i < kMaxChunks; ++i) { 82 uint32_t ssrc = kSenderSsrc + i; 83 StringBuilder oss; 84 oss << "cname" << i; 85 EXPECT_TRUE(sdes.AddCName(ssrc, oss.str())); 86 } 87 EXPECT_FALSE(sdes.AddCName(kSenderSsrc + kMaxChunks, "foo")); 88 } 89 90 TEST(RtcpPacketSdesTest, CreateAndParseCnameItemWithEmptyString) { 91 Sdes sdes; 92 EXPECT_TRUE(sdes.AddCName(kSenderSsrc, "")); 93 94 Buffer packet = sdes.Build(); 95 Sdes parsed; 96 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed)); 97 98 EXPECT_EQ(1u, parsed.chunks().size()); 99 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); 100 EXPECT_EQ("", parsed.chunks()[0].cname); 101 } 102 103 TEST(RtcpPacketSdesTest, ParseSkipsNonCNameField) { 104 const uint8_t kName[] = "abc"; 105 const uint8_t kCname[] = "de"; 106 const uint8_t kValidPacket[] = { 107 0x81, 202, 0x00, 0x04, 0x12, 0x34, 0x56, 108 0x78, kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag, 109 2, kCname[0], kCname[1], kTerminatorTag, kPadding, kPadding}; 110 // Sanity checks packet was assembled correctly. 111 ASSERT_EQ(0u, sizeof(kValidPacket) % 4); 112 ASSERT_EQ(kValidPacket[3] + 1u, sizeof(kValidPacket) / 4); 113 114 Sdes parsed; 115 EXPECT_TRUE(test::ParseSinglePacket(kValidPacket, &parsed)); 116 117 EXPECT_EQ(1u, parsed.chunks().size()); 118 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); 119 EXPECT_EQ("de", parsed.chunks()[0].cname); 120 } 121 122 TEST(RtcpPacketSdesTest, ParseSkipsChunksWithoutCName) { 123 const uint8_t kName[] = "ab"; 124 const uint8_t kEmail[] = "de"; 125 const uint8_t kCname[] = "def"; 126 const uint8_t kPacket[] = { 127 0x82, 202, 0x00, 0x07, 0x12, 128 0x34, 0x56, 0x78, // 1st chunk. 129 kNameTag, 3, kName[0], kName[1], kName[2], 130 kEmailTag, 2, kEmail[0], kEmail[1], kTerminatorTag, 131 kPadding, kPadding, 0x23, 0x45, 0x67, 132 0x89, // 2nd chunk. 133 kCnameTag, 3, kCname[0], kCname[1], kCname[2], 134 kTerminatorTag, kPadding, kPadding}; 135 // Sanity checks packet was assembled correctly. 136 ASSERT_EQ(0u, sizeof(kPacket) % 4); 137 ASSERT_EQ(kPacket[3] + 1u, sizeof(kPacket) / 4); 138 139 Sdes parsed; 140 EXPECT_TRUE(test::ParseSinglePacket(kPacket, &parsed)); 141 ASSERT_EQ(1u, parsed.chunks().size()); 142 EXPECT_EQ(0x23456789u, parsed.chunks()[0].ssrc); 143 EXPECT_EQ("def", parsed.chunks()[0].cname); 144 } 145 146 TEST(RtcpPacketSdesTest, ParseFailsWithoutChunkItemTerminator) { 147 const uint8_t kName[] = "abc"; 148 const uint8_t kCname[] = "d"; 149 // No place for next chunk item. 150 const uint8_t kInvalidPacket[] = { 151 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, 152 kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag, 1, kCname[0]}; 153 // Sanity checks packet was assembled correctly. 154 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); 155 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); 156 157 Sdes parsed; 158 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed)); 159 } 160 161 TEST(RtcpPacketSdesTest, ParseFailsWithDamagedChunkItem) { 162 const uint8_t kName[] = "ab"; 163 const uint8_t kCname[] = "d"; 164 // Next chunk item has non-terminator type, but not the size. 165 const uint8_t kInvalidPacket[] = { 166 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, 167 kNameTag, 2, kName[0], kName[1], kCnameTag, 1, kCname[0], kEmailTag}; 168 // Sanity checks packet was assembled correctly. 169 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); 170 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); 171 172 Sdes parsed; 173 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed)); 174 } 175 176 TEST(RtcpPacketSdesTest, ParseFailsWithTooLongChunkItem) { 177 const uint8_t kName[] = "abc"; 178 const uint8_t kCname[] = "d"; 179 // Last chunk item has length that goes beyond the buffer end. 180 const uint8_t kInvalidPacket[] = { 181 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78, 182 kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag, 2, kCname[0]}; 183 // Sanity checks packet was assembled correctly. 184 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); 185 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); 186 187 Sdes parsed; 188 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed)); 189 } 190 191 TEST(RtcpPacketSdesTest, ParseFailsWithTwoCNames) { 192 const uint8_t kCname1[] = "a"; 193 const uint8_t kCname2[] = "de"; 194 const uint8_t kInvalidPacket[] = { 195 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 196 0x78, kCnameTag, 1, kCname1[0], kCnameTag, 2, kCname2[0], 197 kCname2[1], kTerminatorTag}; 198 // Sanity checks packet was assembled correctly. 199 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); 200 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); 201 202 Sdes parsed; 203 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed)); 204 } 205 206 TEST(RtcpPacketSdesTest, ParseFailsWithTooLittleSpaceForNextChunk) { 207 const uint8_t kCname[] = "a"; 208 const uint8_t kEmail[] = "de"; 209 // Two chunks are promised in the header, but no place for the second chunk. 210 const uint8_t kInvalidPacket[] = { 211 0x82, 202, 0x00, 0x04, 0x12, 0x34, 0x56, 212 0x78, // 1st chunk. 213 kCnameTag, 1, kCname[0], kEmailTag, 2, kEmail[0], kEmail[1], 214 kTerminatorTag, 0x23, 0x45, 0x67, 0x89}; // 2nd chunk. 215 // Sanity checks packet was assembled correctly. 216 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); 217 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); 218 219 Sdes parsed; 220 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed)); 221 } 222 223 TEST(RtcpPacketSdesTest, ParsedSdesCanBeReusedForBuilding) { 224 Sdes source; 225 const std::string kAlice = "alice@host"; 226 const std::string kBob = "bob@host"; 227 source.AddCName(kSenderSsrc, kAlice); 228 229 Buffer packet1 = source.Build(); 230 Sdes middle; 231 test::ParseSinglePacket(packet1, &middle); 232 233 EXPECT_EQ(source.BlockLength(), middle.BlockLength()); 234 235 middle.AddCName(kSenderSsrc + 1, kBob); 236 237 Buffer packet2 = middle.Build(); 238 Sdes destination; 239 test::ParseSinglePacket(packet2, &destination); 240 241 EXPECT_EQ(middle.BlockLength(), destination.BlockLength()); 242 243 EXPECT_EQ(2u, destination.chunks().size()); 244 EXPECT_EQ(kSenderSsrc, destination.chunks()[0].ssrc); 245 EXPECT_EQ(kAlice, destination.chunks()[0].cname); 246 EXPECT_EQ(kSenderSsrc + 1, destination.chunks()[1].ssrc); 247 EXPECT_EQ(kBob, destination.chunks()[1].cname); 248 } 249 } // namespace webrtc