Index: webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes_unittest.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes_unittest.cc |
index 65f809609615027b475f17738eb7a76a7a4fbc18..04478ce78c68506735c8c33affa66378ce23514b 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes_unittest.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes_unittest.cc |
@@ -12,51 +12,77 @@ |
#include "testing/gtest/include/gtest/gtest.h" |
-#include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
-#include "webrtc/test/rtcp_packet_parser.h" |
- |
using webrtc::rtcp::RawPacket; |
using webrtc::rtcp::Sdes; |
-using webrtc::test::RtcpPacketParser; |
+using webrtc::RTCPUtility::RtcpCommonHeader; |
+using webrtc::RTCPUtility::RtcpParseCommonHeader; |
namespace webrtc { |
+namespace { |
const uint32_t kSenderSsrc = 0x12345678; |
+const uint8_t kPadding = 0; |
+const uint8_t kTerminatorTag = 0; |
+const uint8_t kCnameTag = 1; |
+const uint8_t kNameTag = 2; |
+const uint8_t kEmailTag = 3; |
+ |
+bool Parse(const uint8_t* buffer, size_t length, Sdes* sdes) { |
+ RtcpCommonHeader header; |
+ EXPECT_TRUE(RtcpParseCommonHeader(buffer, length, &header)); |
+ // Check that there is exactly one RTCP packet in the buffer. |
+ EXPECT_EQ(length, header.BlockSize()); |
+ return sdes->Parse(header, buffer + RtcpCommonHeader::kHeaderSizeBytes); |
+} |
+} // namespace |
+ |
+TEST(RtcpPacketSdesTest, WithoutChunks) { |
+ Sdes sdes; |
+ |
+ rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
+ Sdes parsed; |
+ EXPECT_TRUE(Parse(packet->Buffer(), packet->Length(), &parsed)); |
+ |
+ EXPECT_EQ(0u, parsed.chunks().size()); |
+} |
TEST(RtcpPacketSdesTest, WithOneChunk) { |
+ const std::string kCname = "alice@host"; |
+ |
Sdes sdes; |
- EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "alice@host")); |
- |
- rtc::scoped_ptr<RawPacket> packet(sdes.Build()); |
- RtcpPacketParser parser; |
- parser.Parse(packet->Buffer(), packet->Length()); |
- EXPECT_EQ(1, parser.sdes()->num_packets()); |
- EXPECT_EQ(1, parser.sdes_chunk()->num_packets()); |
- EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc()); |
- EXPECT_EQ("alice@host", parser.sdes_chunk()->Cname()); |
+ EXPECT_TRUE(sdes.WithCName(kSenderSsrc, kCname)); |
+ |
+ rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
+ Sdes sdes_parsed; |
+ Parse(packet->Buffer(), packet->Length(), &sdes_parsed); |
+ const Sdes& parsed = sdes_parsed; // Ensure accessors are const. |
+ |
+ EXPECT_EQ(1u, parsed.chunks().size()); |
+ EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
+ EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
} |
TEST(RtcpPacketSdesTest, WithMultipleChunks) { |
Sdes sdes; |
- EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "a")); |
+ EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 0, "a")); |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 1, "ab")); |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 2, "abc")); |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 3, "abcd")); |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 4, "abcde")); |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 5, "abcdef")); |
- rtc::scoped_ptr<RawPacket> packet(sdes.Build()); |
- RtcpPacketParser parser; |
- parser.Parse(packet->Buffer(), packet->Length()); |
- EXPECT_EQ(1, parser.sdes()->num_packets()); |
- EXPECT_EQ(6, parser.sdes_chunk()->num_packets()); |
- EXPECT_EQ(kSenderSsrc + 5, parser.sdes_chunk()->Ssrc()); |
- EXPECT_EQ("abcdef", parser.sdes_chunk()->Cname()); |
+ rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
+ Sdes parsed; |
+ Parse(packet->Buffer(), packet->Length(), &parsed); |
+ |
+ EXPECT_EQ(6u, parsed.chunks().size()); |
+ EXPECT_EQ(kSenderSsrc + 5, parsed.chunks()[5].ssrc); |
+ EXPECT_EQ("abcdef", parsed.chunks()[5].cname); |
} |
TEST(RtcpPacketSdesTest, WithTooManyChunks) { |
+ const size_t kMaxChunks = (1 << 5) - 1; |
Sdes sdes; |
- const int kMaxChunks = (1 << 5) - 1; |
- for (int i = 0; i < kMaxChunks; ++i) { |
+ for (size_t i = 0; i < kMaxChunks; ++i) { |
uint32_t ssrc = kSenderSsrc + i; |
std::ostringstream oss; |
oss << "cname" << i; |
@@ -69,13 +95,165 @@ TEST(RtcpPacketSdesTest, CnameItemWithEmptyString) { |
Sdes sdes; |
EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "")); |
- rtc::scoped_ptr<RawPacket> packet(sdes.Build()); |
- RtcpPacketParser parser; |
- parser.Parse(packet->Buffer(), packet->Length()); |
- EXPECT_EQ(1, parser.sdes()->num_packets()); |
- EXPECT_EQ(1, parser.sdes_chunk()->num_packets()); |
- EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc()); |
- EXPECT_EQ("", parser.sdes_chunk()->Cname()); |
+ rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
+ Sdes parsed; |
+ Parse(packet->Buffer(), packet->Length(), &parsed); |
+ |
+ EXPECT_EQ(1u, parsed.chunks().size()); |
+ EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
+ EXPECT_EQ("", parsed.chunks()[0].cname); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseSkipsNonCNameField) { |
+ const char kName[] = "abc"; |
+ const std::string kCname = "de"; |
+ const uint8_t kValidPacket[] = {0x81, 202, 0x00, 0x04, |
+ 0x12, 0x34, 0x56, 0x78, |
+ kNameTag, 3, kName[0], kName[1], kName[2], |
+ kCnameTag, 2, kCname[0], kCname[1], |
+ kTerminatorTag, kPadding, kPadding}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kValidPacket) % 4); |
+ ASSERT_EQ(kValidPacket[3] + 1u, sizeof(kValidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_TRUE(Parse(kValidPacket, sizeof(kValidPacket), &parsed)); |
+ |
+ EXPECT_EQ(1u, parsed.chunks().size()); |
+ EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
+ EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseSkipsChunksWithoutCName) { |
+ const char kName[] = "ab"; |
+ const char kEmail[] = "de"; |
+ const std::string kCname = "def"; |
+ const uint8_t kPacket[] = {0x82, 202, 0x00, 0x07, |
+ 0x12, 0x34, 0x56, 0x78, // 1st chunk. |
+ kNameTag, 3, kName[0], kName[1], kName[2], |
+ kEmailTag, 2, kEmail[0], kEmail[1], |
+ kTerminatorTag, kPadding, kPadding, |
+ 0x23, 0x45, 0x67, 0x89, // 2nd chunk. |
+ kCnameTag, 3, kCname[0], kCname[1], kCname[2], |
+ kTerminatorTag, kPadding, kPadding}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kPacket) % 4); |
+ ASSERT_EQ(kPacket[3] + 1u, sizeof(kPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_TRUE(Parse(kPacket, sizeof(kPacket), &parsed)); |
+ ASSERT_EQ(1u, parsed.chunks().size()); |
+ EXPECT_EQ(0x23456789u, parsed.chunks()[0].ssrc); |
+ EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseFailsWithoutChunkItemTerminator) { |
+ const char kName[] = "abc"; |
+ const char kCname[] = "d"; |
+ // No place for next chunk item. |
+ const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
+ 0x12, 0x34, 0x56, 0x78, |
+ kNameTag, 3, kName[0], kName[1], kName[2], |
+ kCnameTag, 1, kCname[0]}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
+ ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseFailsWithDamagedChunkItem) { |
+ const char kName[] = "ab"; |
+ const char kCname[] = "d"; |
+ // Next chunk item has non-terminator type, but not the size. |
+ const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
+ 0x12, 0x34, 0x56, 0x78, |
+ kNameTag, 2, kName[0], kName[1], |
+ kCnameTag, 1, kCname[0], |
+ kEmailTag}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
+ ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseFailsWithTooLongChunkItem) { |
+ const char kName[] = "abc"; |
+ const char kCname[] = "d"; |
+ // Last chunk item has length that goes beyond the buffer end. |
+ const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
+ 0x12, 0x34, 0x56, 0x78, |
+ kNameTag, 3, kName[0], kName[1], kName[2], |
+ kCnameTag, 2, kCname[0]}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
+ ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParseFailsWithTwoCNames) { |
+ const char kCname1[] = "a"; |
+ const char kCname2[] = "de"; |
+ const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
+ 0x12, 0x34, 0x56, 0x78, |
+ kCnameTag, 1, kCname1[0], |
+ kCnameTag, 2, kCname2[0], kCname2[1], |
+ kTerminatorTag}; |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
+ ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
} |
+TEST(RtcpPacketSdesTest, ParseFailsWithTooLittleSpaceForNextChunk) { |
+ const char kCname[] = "a"; |
+ const char kEmail[] = "de"; |
+ // Two chunks are promised in the header, but no place for the second chunk. |
+ const uint8_t kInvalidPacket[] = {0x82, 202, 0x00, 0x04, |
+ 0x12, 0x34, 0x56, 0x78, // 1st chunk. |
+ kCnameTag, 1, kCname[0], |
+ kEmailTag, 2, kEmail[0], kEmail[1], |
+ kTerminatorTag, |
+ 0x23, 0x45, 0x67, 0x89}; // 2nd chunk. |
+ // Sanity checks packet was assembled correctly. |
+ ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
+ ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
+ |
+ Sdes parsed; |
+ EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
+} |
+ |
+TEST(RtcpPacketSdesTest, ParsedSdesCanBeReusedForBuilding) { |
+ Sdes source; |
+ const std::string kAlice = "alice@host"; |
+ const std::string kBob = "bob@host"; |
+ source.WithCName(kSenderSsrc, kAlice); |
+ |
+ rtc::scoped_ptr<RawPacket> packet1 = source.Build(); |
+ Sdes middle; |
+ Parse(packet1->Buffer(), packet1->Length(), &middle); |
+ |
+ EXPECT_EQ(source.BlockLength(), middle.BlockLength()); |
+ |
+ middle.WithCName(kSenderSsrc + 1, kBob); |
+ |
+ rtc::scoped_ptr<RawPacket> packet2 = middle.Build(); |
+ Sdes destination; |
+ Parse(packet2->Buffer(), packet2->Length(), &destination); |
+ |
+ EXPECT_EQ(middle.BlockLength(), destination.BlockLength()); |
+ |
+ EXPECT_EQ(2u, destination.chunks().size()); |
+ EXPECT_EQ(kSenderSsrc, destination.chunks()[0].ssrc); |
+ EXPECT_EQ(kAlice, destination.chunks()[0].cname); |
+ EXPECT_EQ(kSenderSsrc + 1, destination.chunks()[1].ssrc); |
+ EXPECT_EQ(kBob, destination.chunks()[1].cname); |
+} |
} // namespace webrtc |