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 // kData[] and kEntropyFlag[] are indexed by packet sequence numbers, which
23 // start at 1, so their first elements are dummy.
24 const char* kData
[] = {
26 // kData[1] must be at least as long as every element of kData[], because
27 // it is used to calculate kDataMaxLen.
35 // The maximum length of an element of kData.
36 const size_t kDataMaxLen
= strlen(kData
[1]);
37 // A suitable test data string, whose length is kDataMaxLen.
38 const char* kDataSingle
= kData
[1];
40 const bool kEntropyFlag
[] = {
52 class QuicFecGroupTest
: public ::testing::Test
{
54 void RunTest(size_t num_packets
, size_t lost_packet
, bool out_of_order
) {
55 // kData[] and kEntropyFlag[] are indexed by packet sequence numbers, which
57 DCHECK_GE(arraysize(kData
), num_packets
);
58 scoped_ptr
<char[]> redundancy(new char[kDataMaxLen
]);
59 for (size_t i
= 0; i
< kDataMaxLen
; i
++) {
62 // XOR in the packets.
63 for (size_t packet
= 1; packet
<= num_packets
; ++packet
) {
64 for (size_t i
= 0; i
< kDataMaxLen
; i
++) {
65 uint8 byte
= i
> strlen(kData
[packet
]) ? 0x00 : kData
[packet
][i
];
66 redundancy
[i
] = redundancy
[i
] ^ byte
;
72 // If we're out of order, send the FEC packet in the position of the
73 // lost packet. Otherwise send all (non-missing) packets, then FEC.
75 // Update the FEC state for each non-lost packet.
76 for (size_t packet
= 1; packet
<= num_packets
; packet
++) {
77 if (packet
== lost_packet
) {
78 ASSERT_FALSE(group
.IsFinished());
81 fec
.redundancy
= StringPiece(redundancy
.get(), kDataMaxLen
);
83 group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, num_packets
+ 1, fec
));
85 QuicPacketHeader header
;
86 header
.packet_sequence_number
= packet
;
87 header
.entropy_flag
= kEntropyFlag
[packet
];
88 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
,
91 ASSERT_TRUE(group
.CanRevive() == (packet
== num_packets
));
94 // Update the FEC state for each non-lost packet.
95 for (size_t packet
= 1; packet
<= num_packets
; packet
++) {
96 if (packet
== lost_packet
) {
100 QuicPacketHeader header
;
101 header
.packet_sequence_number
= packet
;
102 header
.entropy_flag
= kEntropyFlag
[packet
];
103 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
,
105 ASSERT_FALSE(group
.CanRevive());
108 ASSERT_FALSE(group
.IsFinished());
109 // Attempt to revive the missing packet.
112 fec
.redundancy
= StringPiece(redundancy
.get(), kDataMaxLen
);
115 group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, num_packets
+ 1, fec
));
117 QuicPacketHeader header
;
118 char recovered
[kMaxPacketSize
];
119 ASSERT_TRUE(group
.CanRevive());
120 size_t len
= group
.Revive(&header
, recovered
, arraysize(recovered
));
122 << "Failed to revive packet " << lost_packet
<< " out of "
124 EXPECT_EQ(lost_packet
, header
.packet_sequence_number
)
125 << "Failed to revive packet " << lost_packet
<< " out of "
127 // Revived packets have an unknown entropy.
128 EXPECT_FALSE(header
.entropy_flag
);
129 ASSERT_GE(len
, strlen(kData
[lost_packet
])) << "Incorrect length";
130 for (size_t i
= 0; i
< strlen(kData
[lost_packet
]); i
++) {
131 EXPECT_EQ(kData
[lost_packet
][i
], recovered
[i
]);
133 ASSERT_TRUE(group
.IsFinished());
137 TEST_F(QuicFecGroupTest
, UpdateAndRevive
) {
138 RunTest(2, 1, false);
139 RunTest(2, 2, false);
141 RunTest(3, 1, false);
142 RunTest(3, 2, false);
143 RunTest(3, 3, false);
146 TEST_F(QuicFecGroupTest
, UpdateAndReviveOutOfOrder
) {
155 TEST_F(QuicFecGroupTest
, UpdateFecIfReceivedPacketIsNotCovered
) {
156 char data1
[] = "abc123";
157 char redundancy
[arraysize(data1
)];
158 for (size_t i
= 0; i
< arraysize(data1
); i
++) {
159 redundancy
[i
] = data1
[i
];
164 QuicPacketHeader header
;
165 header
.packet_sequence_number
= 3;
166 group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, data1
);
170 fec
.redundancy
= redundancy
;
172 header
.packet_sequence_number
= 2;
173 ASSERT_FALSE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 2, fec
));
176 TEST_F(QuicFecGroupTest
, ProtectsPacketsBefore
) {
177 QuicPacketHeader header
;
178 header
.packet_sequence_number
= 3;
181 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kDataSingle
));
183 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
184 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
185 EXPECT_FALSE(group
.ProtectsPacketsBefore(3));
186 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
187 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
188 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
191 TEST_F(QuicFecGroupTest
, ProtectsPacketsBeforeWithSeveralPackets
) {
192 QuicPacketHeader header
;
193 header
.packet_sequence_number
= 3;
196 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kDataSingle
));
198 header
.packet_sequence_number
= 7;
199 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kDataSingle
));
201 header
.packet_sequence_number
= 5;
202 ASSERT_TRUE(group
.Update(ENCRYPTION_FORWARD_SECURE
, header
, kDataSingle
));
204 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
205 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
206 EXPECT_FALSE(group
.ProtectsPacketsBefore(3));
207 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
208 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
209 EXPECT_TRUE(group
.ProtectsPacketsBefore(6));
210 EXPECT_TRUE(group
.ProtectsPacketsBefore(7));
211 EXPECT_TRUE(group
.ProtectsPacketsBefore(8));
212 EXPECT_TRUE(group
.ProtectsPacketsBefore(9));
213 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
216 TEST_F(QuicFecGroupTest
, ProtectsPacketsBeforeWithFecData
) {
219 fec
.redundancy
= kDataSingle
;
222 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 3, fec
));
224 EXPECT_FALSE(group
.ProtectsPacketsBefore(1));
225 EXPECT_FALSE(group
.ProtectsPacketsBefore(2));
226 EXPECT_TRUE(group
.ProtectsPacketsBefore(3));
227 EXPECT_TRUE(group
.ProtectsPacketsBefore(4));
228 EXPECT_TRUE(group
.ProtectsPacketsBefore(5));
229 EXPECT_TRUE(group
.ProtectsPacketsBefore(50));
232 TEST_F(QuicFecGroupTest
, EffectiveEncryptionLevel
) {
234 EXPECT_EQ(NUM_ENCRYPTION_LEVELS
, group
.effective_encryption_level());
236 QuicPacketHeader header
;
237 header
.packet_sequence_number
= 5;
238 ASSERT_TRUE(group
.Update(ENCRYPTION_INITIAL
, header
, kDataSingle
));
239 EXPECT_EQ(ENCRYPTION_INITIAL
, group
.effective_encryption_level());
243 fec
.redundancy
= kDataSingle
;
244 ASSERT_TRUE(group
.UpdateFec(ENCRYPTION_FORWARD_SECURE
, 7, fec
));
245 EXPECT_EQ(ENCRYPTION_INITIAL
, group
.effective_encryption_level());
247 header
.packet_sequence_number
= 3;
248 ASSERT_TRUE(group
.Update(ENCRYPTION_NONE
, header
, kDataSingle
));
249 EXPECT_EQ(ENCRYPTION_NONE
, group
.effective_encryption_level());