OLD | NEW |
| (Empty) |
1 // Copyright 2013 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_received_packet_manager.h" | |
6 | |
7 #include <algorithm> | |
8 #include <vector> | |
9 | |
10 #include "net/quic/quic_connection_stats.h" | |
11 #include "net/quic/quic_flags.h" | |
12 #include "net/quic/test_tools/quic_received_packet_manager_peer.h" | |
13 #include "testing/gmock/include/gmock/gmock.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 using std::pair; | |
17 using std::vector; | |
18 | |
19 namespace net { | |
20 namespace test { | |
21 | |
22 class EntropyTrackerPeer { | |
23 public: | |
24 static QuicPacketNumber first_gap( | |
25 const QuicReceivedPacketManager::EntropyTracker& tracker) { | |
26 return tracker.first_gap_; | |
27 } | |
28 static QuicPacketNumber largest_observed( | |
29 const QuicReceivedPacketManager::EntropyTracker& tracker) { | |
30 return tracker.largest_observed_; | |
31 } | |
32 static int packets_entropy_size( | |
33 const QuicReceivedPacketManager::EntropyTracker& tracker) { | |
34 return tracker.packets_entropy_.size(); | |
35 } | |
36 static bool IsTrackingPacket( | |
37 const QuicReceivedPacketManager::EntropyTracker& tracker, | |
38 QuicPacketNumber packet_number) { | |
39 return packet_number >= tracker.first_gap_ && | |
40 packet_number < | |
41 (tracker.first_gap_ + tracker.packets_entropy_.size()) && | |
42 tracker.packets_entropy_[packet_number - tracker.first_gap_].second; | |
43 } | |
44 }; | |
45 | |
46 namespace { | |
47 | |
48 // Entropy of individual packets is not tracked if there are no gaps. | |
49 TEST(EntropyTrackerTest, NoGaps) { | |
50 QuicReceivedPacketManager::EntropyTracker tracker; | |
51 | |
52 tracker.RecordPacketEntropyHash(1, 23); | |
53 tracker.RecordPacketEntropyHash(2, 42); | |
54 | |
55 EXPECT_EQ(23 ^ 42, tracker.EntropyHash(2)); | |
56 EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker)); | |
57 | |
58 EXPECT_EQ(2u, EntropyTrackerPeer::largest_observed(tracker)); | |
59 EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
60 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1)); | |
61 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2)); | |
62 } | |
63 | |
64 // Entropy of individual packets is tracked as long as there are gaps. | |
65 // Filling the first gap results in entropy getting garbage collected. | |
66 TEST(EntropyTrackerTest, FillGaps) { | |
67 QuicReceivedPacketManager::EntropyTracker tracker; | |
68 | |
69 tracker.RecordPacketEntropyHash(2, 5); | |
70 tracker.RecordPacketEntropyHash(5, 17); | |
71 tracker.RecordPacketEntropyHash(6, 23); | |
72 tracker.RecordPacketEntropyHash(9, 42); | |
73 | |
74 EXPECT_EQ(1u, EntropyTrackerPeer::first_gap(tracker)); | |
75 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
76 EXPECT_EQ(9, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
77 | |
78 EXPECT_EQ(5, tracker.EntropyHash(2)); | |
79 EXPECT_EQ(5 ^ 17, tracker.EntropyHash(5)); | |
80 EXPECT_EQ(5 ^ 17 ^ 23, tracker.EntropyHash(6)); | |
81 EXPECT_EQ(5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
82 | |
83 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1)); | |
84 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2)); | |
85 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5)); | |
86 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6)); | |
87 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9)); | |
88 | |
89 // Fill the gap at 1. | |
90 tracker.RecordPacketEntropyHash(1, 2); | |
91 | |
92 EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker)); | |
93 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
94 EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
95 | |
96 EXPECT_EQ(2 ^ 5 ^ 17, tracker.EntropyHash(5)); | |
97 EXPECT_EQ(2 ^ 5 ^ 17 ^ 23, tracker.EntropyHash(6)); | |
98 EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
99 | |
100 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 1)); | |
101 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 2)); | |
102 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5)); | |
103 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6)); | |
104 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9)); | |
105 | |
106 // Fill the gap at 4. | |
107 tracker.RecordPacketEntropyHash(4, 2); | |
108 | |
109 EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker)); | |
110 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
111 EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
112 | |
113 EXPECT_EQ(5, tracker.EntropyHash(4)); | |
114 EXPECT_EQ(5 ^ 17, tracker.EntropyHash(5)); | |
115 EXPECT_EQ(5 ^ 17 ^ 23, tracker.EntropyHash(6)); | |
116 EXPECT_EQ(5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
117 | |
118 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 3)); | |
119 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 4)); | |
120 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5)); | |
121 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6)); | |
122 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9)); | |
123 | |
124 // Fill the gap at 3. Entropy for packets 3 to 6 are forgotten. | |
125 tracker.RecordPacketEntropyHash(3, 2); | |
126 | |
127 EXPECT_EQ(7u, EntropyTrackerPeer::first_gap(tracker)); | |
128 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
129 EXPECT_EQ(3, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
130 | |
131 EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
132 | |
133 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 3)); | |
134 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 4)); | |
135 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 5)); | |
136 EXPECT_FALSE(EntropyTrackerPeer::IsTrackingPacket(tracker, 6)); | |
137 EXPECT_TRUE(EntropyTrackerPeer::IsTrackingPacket(tracker, 9)); | |
138 | |
139 // Fill in the rest. | |
140 tracker.RecordPacketEntropyHash(7, 2); | |
141 tracker.RecordPacketEntropyHash(8, 2); | |
142 | |
143 EXPECT_EQ(10u, EntropyTrackerPeer::first_gap(tracker)); | |
144 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
145 EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
146 | |
147 EXPECT_EQ(2 ^ 5 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
148 } | |
149 | |
150 TEST(EntropyTrackerTest, SetCumulativeEntropyUpTo) { | |
151 QuicReceivedPacketManager::EntropyTracker tracker; | |
152 | |
153 tracker.RecordPacketEntropyHash(2, 5); | |
154 tracker.RecordPacketEntropyHash(5, 17); | |
155 tracker.RecordPacketEntropyHash(6, 23); | |
156 tracker.RecordPacketEntropyHash(9, 42); | |
157 | |
158 EXPECT_EQ(1u, EntropyTrackerPeer::first_gap(tracker)); | |
159 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
160 EXPECT_EQ(9, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
161 | |
162 // Inform the tracker about value of the hash at a gap. | |
163 tracker.SetCumulativeEntropyUpTo(3, 7); | |
164 EXPECT_EQ(3u, EntropyTrackerPeer::first_gap(tracker)); | |
165 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
166 EXPECT_EQ(7, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
167 | |
168 EXPECT_EQ(7 ^ 17, tracker.EntropyHash(5)); | |
169 EXPECT_EQ(7 ^ 17 ^ 23, tracker.EntropyHash(6)); | |
170 EXPECT_EQ(7 ^ 17 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
171 | |
172 // Inform the tracker about value of the hash at a known location. | |
173 tracker.SetCumulativeEntropyUpTo(6, 1); | |
174 EXPECT_EQ(7u, EntropyTrackerPeer::first_gap(tracker)); | |
175 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
176 EXPECT_EQ(3, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
177 | |
178 EXPECT_EQ(1 ^ 23 ^ 42, tracker.EntropyHash(9)); | |
179 | |
180 // Inform the tracker about value of the hash at the last location. | |
181 tracker.SetCumulativeEntropyUpTo(9, 21); | |
182 EXPECT_EQ(10u, EntropyTrackerPeer::first_gap(tracker)); | |
183 EXPECT_EQ(9u, EntropyTrackerPeer::largest_observed(tracker)); | |
184 EXPECT_EQ(0, EntropyTrackerPeer::packets_entropy_size(tracker)); | |
185 | |
186 EXPECT_EQ(42 ^ 21, tracker.EntropyHash(9)); | |
187 } | |
188 | |
189 struct TestParams { | |
190 explicit TestParams(QuicVersion version) : version(version) {} | |
191 | |
192 friend std::ostream& operator<<(std::ostream& os, const TestParams& p) { | |
193 os << "{ version: " << QuicVersionToString(p.version) << " }"; | |
194 return os; | |
195 } | |
196 | |
197 QuicVersion version; | |
198 }; | |
199 | |
200 vector<TestParams> GetTestParams() { | |
201 vector<TestParams> params; | |
202 QuicVersionVector all_supported_versions = QuicSupportedVersions(); | |
203 for (size_t i = 0; i < all_supported_versions.size(); ++i) { | |
204 params.push_back(TestParams(all_supported_versions[i])); | |
205 } | |
206 return params; | |
207 } | |
208 | |
209 class QuicReceivedPacketManagerTest | |
210 : public ::testing::TestWithParam<TestParams> { | |
211 protected: | |
212 QuicReceivedPacketManagerTest() : received_manager_(&stats_) { | |
213 received_manager_.SetVersion(GetParam().version); | |
214 } | |
215 | |
216 void RecordPacketReceipt(QuicPacketNumber packet_number, | |
217 QuicPacketEntropyHash entropy_hash) { | |
218 RecordPacketReceipt(packet_number, entropy_hash, QuicTime::Zero()); | |
219 } | |
220 | |
221 void RecordPacketReceipt(QuicPacketNumber packet_number, | |
222 QuicPacketEntropyHash entropy_hash, | |
223 QuicTime receipt_time) { | |
224 QuicPacketHeader header; | |
225 header.packet_number = packet_number; | |
226 header.entropy_hash = entropy_hash; | |
227 received_manager_.RecordPacketReceived(0u, header, receipt_time); | |
228 } | |
229 | |
230 QuicConnectionStats stats_; | |
231 QuicReceivedPacketManager received_manager_; | |
232 }; | |
233 | |
234 INSTANTIATE_TEST_CASE_P(QuicReceivedPacketManagerTest, | |
235 QuicReceivedPacketManagerTest, | |
236 ::testing::ValuesIn(GetTestParams())); | |
237 | |
238 TEST_P(QuicReceivedPacketManagerTest, ReceivedPacketEntropyHash) { | |
239 if (GetParam().version > QUIC_VERSION_33) { | |
240 return; | |
241 } | |
242 vector<pair<QuicPacketNumber, QuicPacketEntropyHash>> entropies; | |
243 entropies.push_back(std::make_pair(1, 12)); | |
244 entropies.push_back(std::make_pair(7, 1)); | |
245 entropies.push_back(std::make_pair(2, 33)); | |
246 entropies.push_back(std::make_pair(5, 3)); | |
247 entropies.push_back(std::make_pair(8, 34)); | |
248 | |
249 for (size_t i = 0; i < entropies.size(); ++i) { | |
250 RecordPacketReceipt(entropies[i].first, entropies[i].second); | |
251 } | |
252 | |
253 std::sort(entropies.begin(), entropies.end()); | |
254 | |
255 QuicPacketEntropyHash hash = 0; | |
256 size_t index = 0; | |
257 for (size_t i = 1; i <= (*entropies.rbegin()).first; ++i) { | |
258 if (entropies[index].first == i) { | |
259 hash ^= entropies[index].second; | |
260 ++index; | |
261 } | |
262 if (i < 3) | |
263 continue; | |
264 EXPECT_EQ(hash, received_manager_.EntropyHash(i)); | |
265 } | |
266 // Reorder by 5 when 2 is received after 7. | |
267 EXPECT_EQ(5u, stats_.max_sequence_reordering); | |
268 EXPECT_EQ(0, stats_.max_time_reordering_us); | |
269 EXPECT_EQ(2u, stats_.packets_reordered); | |
270 } | |
271 | |
272 TEST_P(QuicReceivedPacketManagerTest, EntropyHashBelowLeastObserved) { | |
273 if (GetParam().version > QUIC_VERSION_33) { | |
274 return; | |
275 } | |
276 EXPECT_EQ(0, received_manager_.EntropyHash(0)); | |
277 RecordPacketReceipt(4, 5); | |
278 EXPECT_EQ(0, received_manager_.EntropyHash(3)); | |
279 } | |
280 | |
281 TEST_P(QuicReceivedPacketManagerTest, EntropyHashAboveLargestObserved) { | |
282 if (GetParam().version > QUIC_VERSION_33) { | |
283 return; | |
284 } | |
285 EXPECT_EQ(0, received_manager_.EntropyHash(0)); | |
286 RecordPacketReceipt(4, 5); | |
287 EXPECT_EQ(0, received_manager_.EntropyHash(3)); | |
288 } | |
289 | |
290 TEST_P(QuicReceivedPacketManagerTest, SetCumulativeEntropyUpTo) { | |
291 if (GetParam().version > QUIC_VERSION_33) { | |
292 return; | |
293 } | |
294 vector<pair<QuicPacketNumber, QuicPacketEntropyHash>> entropies; | |
295 entropies.push_back(std::make_pair(1, 12)); | |
296 entropies.push_back(std::make_pair(2, 1)); | |
297 entropies.push_back(std::make_pair(3, 33)); | |
298 entropies.push_back(std::make_pair(4, 3)); | |
299 entropies.push_back(std::make_pair(6, 34)); | |
300 entropies.push_back(std::make_pair(7, 29)); | |
301 | |
302 QuicPacketEntropyHash entropy_hash = 0; | |
303 for (size_t i = 0; i < entropies.size(); ++i) { | |
304 RecordPacketReceipt(entropies[i].first, entropies[i].second); | |
305 entropy_hash ^= entropies[i].second; | |
306 } | |
307 EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7)); | |
308 | |
309 // Now set the entropy hash up to 5 to be 100. | |
310 entropy_hash ^= 100; | |
311 for (size_t i = 0; i < 4; ++i) { | |
312 entropy_hash ^= entropies[i].second; | |
313 } | |
314 QuicReceivedPacketManagerPeer::SetCumulativeEntropyUpTo(&received_manager_, 5, | |
315 100); | |
316 EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7)); | |
317 | |
318 QuicReceivedPacketManagerPeer::SetCumulativeEntropyUpTo(&received_manager_, 1, | |
319 50); | |
320 EXPECT_EQ(entropy_hash, received_manager_.EntropyHash(7)); | |
321 | |
322 // No reordering. | |
323 EXPECT_EQ(0u, stats_.max_sequence_reordering); | |
324 EXPECT_EQ(0, stats_.max_time_reordering_us); | |
325 EXPECT_EQ(0u, stats_.packets_reordered); | |
326 } | |
327 | |
328 TEST_P(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) { | |
329 QuicPacketHeader header; | |
330 header.packet_number = 2u; | |
331 received_manager_.RecordPacketReceived(0u, header, QuicTime::Zero()); | |
332 header.packet_number = 7u; | |
333 received_manager_.RecordPacketReceived(0u, header, QuicTime::Zero()); | |
334 EXPECT_TRUE(received_manager_.IsAwaitingPacket(3u)); | |
335 EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u)); | |
336 EXPECT_TRUE(QuicReceivedPacketManagerPeer::DontWaitForPacketsBefore( | |
337 &received_manager_, 4)); | |
338 EXPECT_FALSE(received_manager_.IsAwaitingPacket(3u)); | |
339 EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u)); | |
340 } | |
341 | |
342 TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) { | |
343 QuicPacketHeader header; | |
344 header.packet_number = 2u; | |
345 QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); | |
346 EXPECT_FALSE(received_manager_.ack_frame_updated()); | |
347 received_manager_.RecordPacketReceived(0u, header, two_ms); | |
348 EXPECT_TRUE(received_manager_.ack_frame_updated()); | |
349 | |
350 QuicFrame ack = received_manager_.GetUpdatedAckFrame(QuicTime::Zero()); | |
351 EXPECT_FALSE(received_manager_.ack_frame_updated()); | |
352 // When UpdateReceivedPacketInfo with a time earlier than the time of the | |
353 // largest observed packet, make sure that the delta is 0, not negative. | |
354 EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time); | |
355 EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); | |
356 | |
357 QuicTime four_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(4); | |
358 ack = received_manager_.GetUpdatedAckFrame(four_ms); | |
359 EXPECT_FALSE(received_manager_.ack_frame_updated()); | |
360 // When UpdateReceivedPacketInfo after not having received a new packet, | |
361 // the delta should still be accurate. | |
362 EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2), | |
363 ack.ack_frame->ack_delay_time); | |
364 // And received packet times won't have change. | |
365 EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); | |
366 | |
367 header.packet_number = 999u; | |
368 received_manager_.RecordPacketReceived(0u, header, two_ms); | |
369 header.packet_number = 4u; | |
370 received_manager_.RecordPacketReceived(0u, header, two_ms); | |
371 header.packet_number = 1000u; | |
372 received_manager_.RecordPacketReceived(0u, header, two_ms); | |
373 EXPECT_TRUE(received_manager_.ack_frame_updated()); | |
374 ack = received_manager_.GetUpdatedAckFrame(two_ms); | |
375 EXPECT_FALSE(received_manager_.ack_frame_updated()); | |
376 // UpdateReceivedPacketInfo should discard any times which can't be | |
377 // expressed on the wire. | |
378 EXPECT_EQ(2u, ack.ack_frame->received_packet_times.size()); | |
379 } | |
380 | |
381 TEST_P(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) { | |
382 EXPECT_FALSE(received_manager_.ack_frame_updated()); | |
383 RecordPacketReceipt(1, 0); | |
384 EXPECT_TRUE(received_manager_.ack_frame_updated()); | |
385 RecordPacketReceipt(6, 0); | |
386 RecordPacketReceipt(2, 0, | |
387 QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1)); | |
388 | |
389 EXPECT_EQ(4u, stats_.max_sequence_reordering); | |
390 EXPECT_EQ(1000, stats_.max_time_reordering_us); | |
391 EXPECT_EQ(1u, stats_.packets_reordered); | |
392 } | |
393 | |
394 } // namespace | |
395 } // namespace test | |
396 } // namespace net | |
OLD | NEW |