1 /*
2 * Copyright (c) 2019 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/loss_notification.h"
12
13 #include "test/gmock.h"
14 #include "test/gtest.h"
15 #include "test/rtcp_packet_parser.h"
16
17 namespace webrtc {
18
19 using ::testing::ElementsAreArray;
20 using ::testing::make_tuple;
21 using ::webrtc::rtcp::LossNotification;
22
TEST(RtcpPacketLossNotificationTest,SetWithIllegalValuesFails)23 TEST(RtcpPacketLossNotificationTest, SetWithIllegalValuesFails) {
24 constexpr uint16_t kLastDecoded = 0x3c7b;
25 constexpr uint16_t kLastReceived = kLastDecoded + 0x7fff + 1;
26 constexpr bool kDecodabilityFlag = true;
27 LossNotification loss_notification;
28 EXPECT_FALSE(
29 loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
30 }
31
TEST(RtcpPacketLossNotificationTest,SetWithLegalValuesSucceeds)32 TEST(RtcpPacketLossNotificationTest, SetWithLegalValuesSucceeds) {
33 constexpr uint16_t kLastDecoded = 0x3c7b;
34 constexpr uint16_t kLastReceived = kLastDecoded + 0x7fff;
35 constexpr bool kDecodabilityFlag = true;
36 LossNotification loss_notification;
37 EXPECT_TRUE(
38 loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
39 }
40
TEST(RtcpPacketLossNotificationTest,CreateProducesExpectedWireFormat)41 TEST(RtcpPacketLossNotificationTest, CreateProducesExpectedWireFormat) {
42 // Note that (0x6542 >> 1) is used just to make the pattern in kPacket
43 // more apparent; there's nothing truly special about the value,
44 // it's only an implementation detail that last-received is represented
45 // as a delta from last-decoded, and that this delta is shifted before
46 // it's put on the wire.
47 constexpr uint16_t kLastDecoded = 0x3c7b;
48 constexpr uint16_t kLastReceived = kLastDecoded + (0x6542 >> 1);
49 constexpr bool kDecodabilityFlag = true;
50
51 const uint8_t kPacket[] = {0x8f, 206, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, //
52 0xab, 0xcd, 0xef, 0x01, 'L', 'N', 'T', 'F', //
53 0x3c, 0x7b, 0x65, 0x43};
54
55 LossNotification loss_notification;
56 loss_notification.SetSenderSsrc(0x12345678);
57 loss_notification.SetMediaSsrc(0xabcdef01);
58 ASSERT_TRUE(
59 loss_notification.Set(kLastDecoded, kLastReceived, kDecodabilityFlag));
60
61 rtc::Buffer packet = loss_notification.Build();
62
63 EXPECT_THAT(make_tuple(packet.data(), packet.size()),
64 ElementsAreArray(kPacket));
65 }
66
TEST(RtcpPacketLossNotificationTest,ParseFailsOnTooSmallPacketToBeLossNotification)67 TEST(RtcpPacketLossNotificationTest,
68 ParseFailsOnTooSmallPacketToBeLossNotification) {
69 uint8_t packet[] = {0x8f, 206, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, //
70 0xab, 0xcd, 0xef, 0x01, 'L', 'N', 'T', 'F', //
71 0x3c, 0x7b, 0x65, 0x43};
72 size_t packet_length_bytes = sizeof(packet);
73
74 LossNotification loss_notification;
75
76 // First, prove that the failure we're expecting to see happens because of
77 // the length, by showing that before the modification to the length,
78 // the packet was correctly parsed.
79 ASSERT_TRUE(
80 test::ParseSinglePacket(packet, packet_length_bytes, &loss_notification));
81
82 // Show that after shaving off a word, the packet is no longer parsable.
83 packet[3] -= 1; // Change the `length` field of the RTCP packet.
84 packet_length_bytes -= 4; // Effectively forget the last 32-bit word.
85 EXPECT_FALSE(
86 test::ParseSinglePacket(packet, packet_length_bytes, &loss_notification));
87 }
88
TEST(RtcpPacketLossNotificationTest,ParseFailsWhenUniqueIdentifierIsNotLossNotification)89 TEST(RtcpPacketLossNotificationTest,
90 ParseFailsWhenUniqueIdentifierIsNotLossNotification) {
91 uint8_t packet[] = {0x8f, 206, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, //
92 0xab, 0xcd, 0xef, 0x01, 'L', 'N', 'T', 'F', //
93 0x3c, 0x7b, 0x65, 0x43};
94
95 LossNotification loss_notification;
96
97 // First, prove that the failure we're expecting to see happens because of
98 // the identifier, by showing that before the modification to the identifier,
99 // the packet was correctly parsed.
100 ASSERT_TRUE(test::ParseSinglePacket(packet, &loss_notification));
101
102 // Show that after changing the identifier, the packet is no longer parsable.
103 RTC_DCHECK_EQ(packet[12], 'L');
104 RTC_DCHECK_EQ(packet[13], 'N');
105 RTC_DCHECK_EQ(packet[14], 'T');
106 RTC_DCHECK_EQ(packet[15], 'F');
107 packet[14] = 'x';
108 EXPECT_FALSE(test::ParseSinglePacket(packet, &loss_notification));
109 }
110
TEST(RtcpPacketLossNotificationTest,ParseLegalLossNotificationMessagesCorrectly)111 TEST(RtcpPacketLossNotificationTest,
112 ParseLegalLossNotificationMessagesCorrectly) {
113 // Note that (0x6542 >> 1) is used just to make the pattern in kPacket
114 // more apparent; there's nothing truly special about the value,
115 // it's only an implementation detail that last-received is represented
116 // as a delta from last-decoded, and that this delta is shifted before
117 // it's put on the wire.
118 constexpr uint16_t kLastDecoded = 0x3c7b;
119 constexpr uint16_t kLastReceived = kLastDecoded + (0x6542 >> 1);
120 constexpr bool kDecodabilityFlag = true;
121
122 const uint8_t kPacket[] = {0x8f, 206, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, //
123 0xab, 0xcd, 0xef, 0x01, 'L', 'N', 'T', 'F', //
124 0x3c, 0x7b, 0x65, 0x43};
125
126 LossNotification loss_notification;
127 EXPECT_TRUE(test::ParseSinglePacket(kPacket, &loss_notification));
128
129 EXPECT_EQ(loss_notification.sender_ssrc(), 0x12345678u);
130 EXPECT_EQ(loss_notification.media_ssrc(), 0xabcdef01u);
131 EXPECT_EQ(loss_notification.last_decoded(), kLastDecoded);
132 EXPECT_EQ(loss_notification.last_received(), kLastReceived);
133 EXPECT_EQ(loss_notification.decodability_flag(), kDecodabilityFlag);
134 }
135
136 } // namespace webrtc
137