Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: net/quic/quic_fec_group_test.cc

Issue 2011653004: Remove obsolete fields in quic_protocol and their current usage in QUIC. Reorders QuicAckFrame fie… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@122721477
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_fec_group_interface.cc ('k') | net/quic/quic_framer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "net/quic/quic_fec_group.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <vector>
10
11 #include "base/logging.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13
14 using ::testing::_;
15 using base::StringPiece;
16 using std::string;
17
18 namespace net {
19
20 namespace {
21
22 // kData[] and kEntropyFlag[] are indexed by packet numbers, which
23 // start at 1, so their first elements are dummy.
24 const char* kData[] = {
25 "", // dummy
26 // kData[1] must be at least as long as every element of kData[], because
27 // it is used to calculate kDataMaxLen.
28 "abc12345678", "987defg", "ghi12345", "987jlkmno", "mno4567890",
29 "789pqrstuvw",
30 };
31 // The maximum length of an element of kData.
32 const size_t kDataMaxLen = strlen(kData[1]);
33 // A suitable test data string, whose length is kDataMaxLen.
34 const char* kDataSingle = kData[1];
35
36 const bool kEntropyFlag[] = {
37 false, // dummy
38 false, true, true, false, true, true,
39 };
40
41 } // namespace
42
43 class QuicFecGroupTest : public ::testing::Test {
44 protected:
45 void RunTest(size_t num_packets, size_t lost_packet, bool out_of_order) {
46 // kData[] and kEntropyFlag[] are indexed by packet numbers, which
47 // start at 1.
48 DCHECK_GE(arraysize(kData), num_packets);
49 std::unique_ptr<char[]> redundancy(new char[kDataMaxLen]);
50 for (size_t i = 0; i < kDataMaxLen; i++) {
51 redundancy[i] = 0x00;
52 }
53 // XOR in the packets.
54 for (size_t packet = 1; packet <= num_packets; ++packet) {
55 for (size_t i = 0; i < kDataMaxLen; i++) {
56 uint8_t byte = i > strlen(kData[packet]) ? 0x00 : kData[packet][i];
57 redundancy[i] = redundancy[i] ^ byte;
58 }
59 }
60
61 QuicFecGroup group(1);
62
63 // If we're out of order, send the FEC packet in the position of the
64 // lost packet. Otherwise send all (non-missing) packets, then FEC.
65 if (out_of_order) {
66 // Update the FEC state for each non-lost packet.
67 for (size_t packet = 1; packet <= num_packets; packet++) {
68 if (packet == lost_packet) {
69 QuicPacketHeader header;
70 header.packet_number = num_packets + 1;
71 header.fec_group = 1;
72 ASSERT_FALSE(group.IsFinished());
73 ASSERT_TRUE(
74 group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header,
75 StringPiece(redundancy.get(), kDataMaxLen)));
76 } else {
77 QuicPacketHeader header;
78 header.packet_number = packet;
79 header.fec_group = 1;
80 ASSERT_TRUE(
81 group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[packet]));
82 }
83 ASSERT_TRUE(group.CanRevive() == (packet == num_packets));
84 }
85 } else {
86 // Update the FEC state for each non-lost packet.
87 for (size_t packet = 1; packet <= num_packets; packet++) {
88 if (packet == lost_packet) {
89 continue;
90 }
91
92 QuicPacketHeader header;
93 header.packet_number = packet;
94 header.fec_group = 1;
95 header.entropy_flag = kEntropyFlag[packet];
96 ASSERT_TRUE(
97 group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[packet]));
98 ASSERT_FALSE(group.CanRevive());
99 }
100
101 ASSERT_FALSE(group.IsFinished());
102 QuicPacketHeader header;
103 header.packet_number = num_packets + 1;
104 header.fec_group = 1;
105 // Attempt to revive the missing packet.
106 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header,
107 StringPiece(redundancy.get(), kDataMaxLen)));
108 }
109 QuicPacketHeader header;
110 char recovered[kMaxPacketSize];
111 ASSERT_TRUE(group.CanRevive());
112 size_t len = group.Revive(&header, recovered, arraysize(recovered));
113 ASSERT_NE(0u, len) << "Failed to revive packet " << lost_packet
114 << " out of " << num_packets;
115 EXPECT_EQ(lost_packet, header.packet_number) << "Failed to revive packet "
116 << lost_packet << " out of "
117 << num_packets;
118 // Revived packets have an unknown entropy.
119 EXPECT_FALSE(header.entropy_flag);
120 ASSERT_GE(len, strlen(kData[lost_packet])) << "Incorrect length";
121 for (size_t i = 0; i < strlen(kData[lost_packet]); i++) {
122 EXPECT_EQ(kData[lost_packet][i], recovered[i]);
123 }
124 ASSERT_TRUE(group.IsFinished());
125 }
126 };
127
128 TEST_F(QuicFecGroupTest, UpdateAndRevive) {
129 RunTest(2, 1, false);
130 RunTest(2, 2, false);
131
132 RunTest(3, 1, false);
133 RunTest(3, 2, false);
134 RunTest(3, 3, false);
135 }
136
137 TEST_F(QuicFecGroupTest, UpdateAndReviveOutOfOrder) {
138 RunTest(2, 1, true);
139 RunTest(2, 2, true);
140
141 RunTest(3, 1, true);
142 RunTest(3, 2, true);
143 RunTest(3, 3, true);
144 }
145
146 TEST_F(QuicFecGroupTest, UpdateFecIfReceivedPacketIsNotCovered) {
147 char data1[] = "abc123";
148 char redundancy[arraysize(data1)];
149 for (size_t i = 0; i < arraysize(data1); i++) {
150 redundancy[i] = data1[i];
151 }
152
153 QuicFecGroup group(1);
154
155 QuicPacketHeader header;
156 header.fec_group = 1;
157 header.packet_number = 3;
158 group.Update(ENCRYPTION_FORWARD_SECURE, header, data1);
159
160 header.packet_number = 2;
161 ASSERT_FALSE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header, redundancy));
162 }
163
164 TEST_F(QuicFecGroupTest, IsWaitingForPacketBefore) {
165 QuicPacketHeader header;
166 header.fec_group = 3;
167 header.packet_number = 3;
168
169 QuicFecGroup group(3);
170 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
171
172 EXPECT_FALSE(group.IsWaitingForPacketBefore(1));
173 EXPECT_FALSE(group.IsWaitingForPacketBefore(2));
174 EXPECT_FALSE(group.IsWaitingForPacketBefore(3));
175 EXPECT_FALSE(group.IsWaitingForPacketBefore(4));
176 EXPECT_TRUE(group.IsWaitingForPacketBefore(5));
177 EXPECT_TRUE(group.IsWaitingForPacketBefore(50));
178 }
179
180 TEST_F(QuicFecGroupTest, IsWaitingForPacketBeforeWithSeveralPackets) {
181 QuicPacketHeader header;
182 header.fec_group = 3;
183 header.packet_number = 3;
184
185 QuicFecGroup group(3);
186 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
187
188 header.packet_number = 7;
189 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
190
191 header.packet_number = 5;
192 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
193
194 EXPECT_FALSE(group.IsWaitingForPacketBefore(1));
195 EXPECT_FALSE(group.IsWaitingForPacketBefore(2));
196 EXPECT_FALSE(group.IsWaitingForPacketBefore(3));
197 EXPECT_FALSE(group.IsWaitingForPacketBefore(4));
198 EXPECT_TRUE(group.IsWaitingForPacketBefore(5));
199 EXPECT_TRUE(group.IsWaitingForPacketBefore(6));
200 EXPECT_TRUE(group.IsWaitingForPacketBefore(7));
201 EXPECT_TRUE(group.IsWaitingForPacketBefore(8));
202 EXPECT_TRUE(group.IsWaitingForPacketBefore(9));
203 EXPECT_TRUE(group.IsWaitingForPacketBefore(50));
204 }
205
206 TEST_F(QuicFecGroupTest, IsWaitingForPacketBeforeWithFecData1) {
207 QuicFecGroup group(3);
208
209 QuicPacketHeader header;
210 header.fec_group = 3;
211 header.packet_number = 4;
212 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
213
214 EXPECT_FALSE(group.IsWaitingForPacketBefore(1));
215 EXPECT_FALSE(group.IsWaitingForPacketBefore(2));
216 EXPECT_FALSE(group.IsWaitingForPacketBefore(3));
217 EXPECT_TRUE(group.IsWaitingForPacketBefore(4));
218 EXPECT_TRUE(group.IsWaitingForPacketBefore(5));
219 EXPECT_TRUE(group.IsWaitingForPacketBefore(6));
220 EXPECT_TRUE(group.IsWaitingForPacketBefore(50));
221 }
222
223 TEST_F(QuicFecGroupTest, IsWaitingForPacketBeforeWithFecData2) {
224 QuicFecGroup group(3);
225
226 QuicPacketHeader header;
227 header.fec_group = 3;
228 header.packet_number = 3;
229 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
230
231 header.packet_number = 5;
232 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
233
234 EXPECT_FALSE(group.IsWaitingForPacketBefore(1));
235 EXPECT_FALSE(group.IsWaitingForPacketBefore(2));
236 EXPECT_FALSE(group.IsWaitingForPacketBefore(3));
237 EXPECT_FALSE(group.IsWaitingForPacketBefore(4));
238 EXPECT_TRUE(group.IsWaitingForPacketBefore(5));
239 EXPECT_TRUE(group.IsWaitingForPacketBefore(6));
240 EXPECT_TRUE(group.IsWaitingForPacketBefore(50));
241 }
242
243 TEST_F(QuicFecGroupTest, EffectiveEncryptionLevel) {
244 QuicFecGroup group(1);
245 EXPECT_EQ(NUM_ENCRYPTION_LEVELS, group.EffectiveEncryptionLevel());
246
247 QuicPacketHeader header;
248 header.fec_group = 1;
249 header.packet_number = 5;
250 ASSERT_TRUE(group.Update(ENCRYPTION_INITIAL, header, kDataSingle));
251 EXPECT_EQ(ENCRYPTION_INITIAL, group.EffectiveEncryptionLevel());
252
253 header.packet_number = 7;
254 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, header, kDataSingle));
255 EXPECT_EQ(ENCRYPTION_INITIAL, group.EffectiveEncryptionLevel());
256
257 header.packet_number = 3;
258 ASSERT_TRUE(group.Update(ENCRYPTION_NONE, header, kDataSingle));
259 EXPECT_EQ(ENCRYPTION_NONE, group.EffectiveEncryptionLevel());
260 }
261
262 // Test the code assuming it is going to be operating in 128-bit chunks (which
263 // is something that can happen if it is compiled with full vectorization).
264 const QuicByteCount kWordSize = 128 / 8;
265
266 // A buffer which stores the data with the specified offset with respect to word
267 // alignment boundary.
268 class MisalignedBuffer {
269 public:
270 MisalignedBuffer(const string& original, size_t offset);
271
272 char* buffer() { return buffer_; }
273 size_t size() { return size_; }
274
275 StringPiece AsStringPiece() { return StringPiece(buffer_, size_); }
276
277 private:
278 char* buffer_;
279 size_t size_;
280
281 std::unique_ptr<char[]> allocation_;
282 };
283
284 MisalignedBuffer::MisalignedBuffer(const string& original, size_t offset) {
285 CHECK_LT(offset, kWordSize);
286 size_ = original.size();
287
288 // Allocate aligned buffer two words larger than needed.
289 const size_t aligned_buffer_size = size_ + 2 * kWordSize;
290 allocation_.reset(new char[aligned_buffer_size]);
291 char* aligned_buffer =
292 allocation_.get() +
293 (kWordSize - reinterpret_cast<uintptr_t>(allocation_.get()) % kWordSize);
294 CHECK_EQ(0u, reinterpret_cast<uintptr_t>(aligned_buffer) % kWordSize);
295
296 buffer_ = aligned_buffer + offset;
297 CHECK_EQ(offset, reinterpret_cast<uintptr_t>(buffer_) % kWordSize);
298 memcpy(buffer_, original.data(), size_);
299 }
300
301 // Checks whether XorBuffers works correctly with buffers aligned in various
302 // ways.
303 TEST(XorBuffersTest, XorBuffers) {
304 const string longer_data =
305 "Having to care about memory alignment can be incredibly frustrating.";
306 const string shorter_data = "strict aliasing";
307
308 // Compute the reference XOR using simpler slow way.
309 string output_reference;
310 for (size_t i = 0; i < longer_data.size(); i++) {
311 char shorter_byte = i < shorter_data.size() ? shorter_data[i] : 0;
312 output_reference.push_back(longer_data[i] ^ shorter_byte);
313 }
314
315 // Check whether XorBuffers works correctly for all possible misalignments.
316 for (size_t offset_shorter = 0; offset_shorter < kWordSize;
317 offset_shorter++) {
318 for (size_t offset_longer = 0; offset_longer < kWordSize; offset_longer++) {
319 // Prepare the misaligned buffer.
320 MisalignedBuffer longer(longer_data, offset_longer);
321 MisalignedBuffer shorter(shorter_data, offset_shorter);
322
323 // XOR the buffers and compare the result with the reference.
324 QuicFecGroup::XorBuffers(shorter.buffer(), shorter.size(),
325 longer.buffer());
326 EXPECT_EQ(output_reference, longer.AsStringPiece());
327 }
328 }
329 }
330
331 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_fec_group_interface.cc ('k') | net/quic/quic_framer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698