1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_fec_group.h"
10 #include "base/basictypes.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "testing/gmock/include/gmock/gmock.h"
16 using base::StringPiece
;
22 const char* const kData
[] = {
31 const bool kEntropyFlag
[] = {
42 class QuicFecGroupTest
: public ::testing::Test
{
44 void RunTest(size_t num_packets
, size_t lost_packet
, bool out_of_order
) {
45 size_t max_len
= strlen(kData
[0]);
46 scoped_ptr
<char[]> redundancy(new char[max_len
]);
47 for (size_t packet
= 0; packet
< num_packets
; ++packet
) {
48 for (size_t i
= 0; i
< max_len
; i
++) {
50 // Initialize to the first packet.
51 redundancy
[i
] = kData
[0][i
];
54 // XOR in the remaining packets.
55 uint8 byte
= i
> strlen(kData
[packet
]) ? 0x00 : kData
[packet
][i
];
56 redundancy
[i
] = redundancy
[i
] ^ byte
;
62 // If we're out of order, send the FEC packet in the position of the
63 // lost packet. Otherwise send all (non-missing) packets, then FEC.
65 // Update the FEC state for each non-lost packet.
66 for (size_t packet
= 0; packet
< num_packets
; packet
++) {
67 if (packet
== lost_packet
) {
68 ASSERT_FALSE(group
.IsFinished());
71 fec
.redundancy
= StringPiece(redundancy
.get(), strlen(kData
[0]));
72 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, num_packets
,
75 QuicPacketHeader header
;
76 header
.packet_sequence_number
= packet
;
77 header
.entropy_flag
= kEntropyFlag
[packet
];
78 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
,
81 ASSERT_TRUE(group
.CanRevive() == (packet
== num_packets
- 1));
84 // Update the FEC state for each non-lost packet.
85 for (size_t packet
= 0; packet
< num_packets
; packet
++) {
86 if (packet
== lost_packet
) {
90 QuicPacketHeader header
;
91 header
.packet_sequence_number
= packet
;
92 header
.entropy_flag
= kEntropyFlag
[packet
];
93 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
,
95 ASSERT_FALSE(group
.CanRevive());
98 ASSERT_FALSE(group
.IsFinished());
99 // Attempt to revive the missing packet.
102 fec
.redundancy
= StringPiece(redundancy
.get(), strlen(kData
[0]));
104 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, num_packets
,
107 QuicPacketHeader header
;
108 char recovered
[kMaxPacketSize
];
109 ASSERT_TRUE(group
.CanRevive());
110 size_t len
= group
.Revive(&header
, recovered
, arraysize(recovered
));
112 << "Failed to revive packet " << lost_packet
<< " out of "
114 EXPECT_EQ(lost_packet
, header
.packet_sequence_number
)
115 << "Failed to revive packet " << lost_packet
<< " out of "
117 // Revived packets have an unknown entropy.
118 EXPECT_FALSE(header
.entropy_flag
);
119 ASSERT_GE(len
, strlen(kData
[lost_packet
])) << "Incorrect length";
120 for (size_t i
= 0; i
< strlen(kData
[lost_packet
]); i
++) {
121 EXPECT_EQ(kData
[lost_packet
][i
], recovered
[i
]);
123 ASSERT_TRUE(group
.IsFinished());
127 TEST_F(QuicFecGroupTest
, UpdateAndRevive
) {
128 RunTest(2, 0, false);
129 RunTest(2, 1, false);
131 RunTest(3, 0, false);
132 RunTest(3, 1, false);
133 RunTest(3, 2, false);
136 TEST_F(QuicFecGroupTest
, UpdateAndReviveOutOfOrder
) {
145 TEST_F(QuicFecGroupTest
, UpdateFecIfReceivedPacketIsNotCovered
) {
146 char data1
[] = "abc123";
147 char redundancy
[arraysize(data1
)];
148 for (size_t i
= 0; i
< arraysize(data1
); i
++) {
149 redundancy
[i
] = data1
[i
];
154 QuicPacketHeader header
;
155 header
.packet_sequence_number
= 3;
156 group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, data1
);
160 fec
.redundancy
= redundancy
;
162 header
.packet_sequence_number
= 2;
163 ASSERT_FALSE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 2, fec
));
166 TEST_F(QuicFecGroupTest
, ProtectsPacketsBefore
) {
167 QuicPacketHeader header
;
168 header
.packet_sequence_number
= 3;
171 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kData
[0]));
173 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
174 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
175 EXPECT_FALSE(group
.ProtectsPacketsBefore(3));
176 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
177 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
178 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
181 TEST_F(QuicFecGroupTest
, ProtectsPacketsBeforeWithSeveralPackets
) {
182 QuicPacketHeader header
;
183 header
.packet_sequence_number
= 3;
186 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kData
[0]));
188 header
.packet_sequence_number
= 7;
189 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kData
[0]));
191 header
.packet_sequence_number
= 5;
192 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kData
[0]));
194 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
195 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
196 EXPECT_FALSE(group
.ProtectsPacketsBefore(3));
197 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
198 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
199 EXPECT_TRUE(group
.ProtectsPacketsBefore(6));
200 EXPECT_TRUE(group
.ProtectsPacketsBefore(7));
201 EXPECT_TRUE(group
.ProtectsPacketsBefore(8));
202 EXPECT_TRUE(group
.ProtectsPacketsBefore(9));
203 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
206 TEST_F(QuicFecGroupTest
, ProtectsPacketsBeforeWithFecData
) {
209 fec
.redundancy
= kData
[0];
212 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 3, fec
));
214 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
215 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
216 EXPECT_TRUE(group
.ProtectsPacketsBefore(3));
217 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
218 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
219 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
222 TEST_F(QuicFecGroupTest
, EffectiveEncryptionLevel
) {
224 EXPECT_EQ(NUM_ENCRYPTION_LEVELS
, group
.effective_encryption_level());
226 QuicPacketHeader header
;
227 header
.packet_sequence_number
= 5;
228 ASSERT_TRUE(group
.Update(ENCRYPTION_INITIAL
, header
, kData
[0]));
229 EXPECT_EQ(ENCRYPTION_INITIAL
, group
.effective_encryption_level());
233 fec
.redundancy
= kData
[0];
234 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 7, fec
));
235 EXPECT_EQ(ENCRYPTION_INITIAL
, group
.effective_encryption_level());
237 header
.packet_sequence_number
= 3;
238 ASSERT_TRUE(group
.Update(ENCRYPTION_NONE
, header
, kData
[0]));
239 EXPECT_EQ(ENCRYPTION_NONE
, group
.effective_encryption_level());