OLD | NEW |
| (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 <vector> | |
9 | |
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" | |
14 | |
15 using ::testing::_; | |
16 using base::StringPiece; | |
17 | |
18 namespace net { | |
19 | |
20 namespace { | |
21 | |
22 const char* const kData[] = { | |
23 "abc12345678", | |
24 "987defg", | |
25 "ghi12345", | |
26 "987jlkmno", | |
27 "mno4567890", | |
28 "789pqrstuvw", | |
29 }; | |
30 | |
31 const bool kEntropyFlag[] = { | |
32 false, | |
33 true, | |
34 true, | |
35 false, | |
36 true, | |
37 true, | |
38 }; | |
39 | |
40 } // namespace | |
41 | |
42 class QuicFecGroupTest : public ::testing::Test { | |
43 protected: | |
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++) { | |
49 if (packet == 0) { | |
50 // Initialize to the first packet. | |
51 redundancy[i] = kData[0][i]; | |
52 continue; | |
53 } | |
54 // XOR in the remaining packets. | |
55 uint8 byte = i > strlen(kData[packet]) ? 0x00 : kData[packet][i]; | |
56 redundancy[i] = redundancy[i] ^ byte; | |
57 } | |
58 } | |
59 | |
60 QuicFecGroup group; | |
61 | |
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. | |
64 if (out_of_order) { | |
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()); | |
69 QuicFecData fec; | |
70 fec.fec_group = 0; | |
71 fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0])); | |
72 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets, | |
73 fec)); | |
74 } else { | |
75 QuicPacketHeader header; | |
76 header.packet_sequence_number = packet; | |
77 header.entropy_flag = kEntropyFlag[packet]; | |
78 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, | |
79 kData[packet])); | |
80 } | |
81 ASSERT_TRUE(group.CanRevive() == (packet == num_packets - 1)); | |
82 } | |
83 } else { | |
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) { | |
87 continue; | |
88 } | |
89 | |
90 QuicPacketHeader header; | |
91 header.packet_sequence_number = packet; | |
92 header.entropy_flag = kEntropyFlag[packet]; | |
93 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, | |
94 kData[packet])); | |
95 ASSERT_FALSE(group.CanRevive()); | |
96 } | |
97 | |
98 ASSERT_FALSE(group.IsFinished()); | |
99 // Attempt to revive the missing packet. | |
100 QuicFecData fec; | |
101 fec.fec_group = 0; | |
102 fec.redundancy = StringPiece(redundancy.get(), strlen(kData[0])); | |
103 | |
104 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, num_packets, | |
105 fec)); | |
106 } | |
107 QuicPacketHeader header; | |
108 char recovered[kMaxPacketSize]; | |
109 ASSERT_TRUE(group.CanRevive()); | |
110 size_t len = group.Revive(&header, recovered, arraysize(recovered)); | |
111 ASSERT_NE(0u, len) | |
112 << "Failed to revive packet " << lost_packet << " out of " | |
113 << num_packets; | |
114 EXPECT_EQ(lost_packet, header.packet_sequence_number) | |
115 << "Failed to revive packet " << lost_packet << " out of " | |
116 << num_packets; | |
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]); | |
122 } | |
123 ASSERT_TRUE(group.IsFinished()); | |
124 } | |
125 }; | |
126 | |
127 TEST_F(QuicFecGroupTest, UpdateAndRevive) { | |
128 RunTest(2, 0, false); | |
129 RunTest(2, 1, false); | |
130 | |
131 RunTest(3, 0, false); | |
132 RunTest(3, 1, false); | |
133 RunTest(3, 2, false); | |
134 } | |
135 | |
136 TEST_F(QuicFecGroupTest, UpdateAndReviveOutOfOrder) { | |
137 RunTest(2, 0, true); | |
138 RunTest(2, 1, true); | |
139 | |
140 RunTest(3, 0, true); | |
141 RunTest(3, 1, true); | |
142 RunTest(3, 2, true); | |
143 } | |
144 | |
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]; | |
150 } | |
151 | |
152 QuicFecGroup group; | |
153 | |
154 QuicPacketHeader header; | |
155 header.packet_sequence_number = 3; | |
156 group.Update(ENCRYPTION_FORWARD_SECURE, header, data1); | |
157 | |
158 QuicFecData fec; | |
159 fec.fec_group = 1; | |
160 fec.redundancy = redundancy; | |
161 | |
162 header.packet_sequence_number = 2; | |
163 ASSERT_FALSE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 2, fec)); | |
164 } | |
165 | |
166 TEST_F(QuicFecGroupTest, ProtectsPacketsBefore) { | |
167 QuicPacketHeader header; | |
168 header.packet_sequence_number = 3; | |
169 | |
170 QuicFecGroup group; | |
171 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0])); | |
172 | |
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)); | |
179 } | |
180 | |
181 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithSeveralPackets) { | |
182 QuicPacketHeader header; | |
183 header.packet_sequence_number = 3; | |
184 | |
185 QuicFecGroup group; | |
186 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0])); | |
187 | |
188 header.packet_sequence_number = 7; | |
189 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0])); | |
190 | |
191 header.packet_sequence_number = 5; | |
192 ASSERT_TRUE(group.Update(ENCRYPTION_FORWARD_SECURE, header, kData[0])); | |
193 | |
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)); | |
204 } | |
205 | |
206 TEST_F(QuicFecGroupTest, ProtectsPacketsBeforeWithFecData) { | |
207 QuicFecData fec; | |
208 fec.fec_group = 2; | |
209 fec.redundancy = kData[0]; | |
210 | |
211 QuicFecGroup group; | |
212 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 3, fec)); | |
213 | |
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)); | |
220 } | |
221 | |
222 TEST_F(QuicFecGroupTest, EffectiveEncryptionLevel) { | |
223 QuicFecGroup group; | |
224 EXPECT_EQ(NUM_ENCRYPTION_LEVELS, group.effective_encryption_level()); | |
225 | |
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()); | |
230 | |
231 QuicFecData fec; | |
232 fec.fec_group = 0; | |
233 fec.redundancy = kData[0]; | |
234 ASSERT_TRUE(group.UpdateFec(ENCRYPTION_FORWARD_SECURE, 7, fec)); | |
235 EXPECT_EQ(ENCRYPTION_INITIAL, group.effective_encryption_level()); | |
236 | |
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()); | |
240 } | |
241 | |
242 } // namespace net | |
OLD | NEW |