OLD | NEW |
| (Empty) |
1 // Copyright (c) 2016 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_buffered_packet_store.h" | |
6 | |
7 #include <list> | |
8 #include <string> | |
9 | |
10 #include "base/stl_util.h" | |
11 #include "net/quic/test_tools/mock_clock.h" | |
12 #include "net/quic/test_tools/quic_test_utils.h" | |
13 #include "testing/gmock/include/gmock/gmock.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 using std::list; | |
17 using std::string; | |
18 | |
19 namespace net { | |
20 | |
21 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; | |
22 typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; | |
23 | |
24 static const size_t kDefaultMaxConnectionsInStore = 100; | |
25 | |
26 namespace test { | |
27 class QuicBufferedPacketStorePeer { | |
28 public: | |
29 static QuicAlarm* expiration_alarm(QuicBufferedPacketStore* store) { | |
30 return store->expiration_alarm_.get(); | |
31 } | |
32 }; | |
33 | |
34 namespace { | |
35 | |
36 typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; | |
37 typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; | |
38 | |
39 class QuicBufferedPacketStoreVisitor | |
40 : public QuicBufferedPacketStore::VisitorInterface { | |
41 public: | |
42 QuicBufferedPacketStoreVisitor() {} | |
43 | |
44 ~QuicBufferedPacketStoreVisitor() override {} | |
45 | |
46 void OnExpiredPackets(QuicConnectionId connection_id, | |
47 BufferedPacketList early_arrived_packets) override { | |
48 last_expired_packet_queue_ = std::move(early_arrived_packets); | |
49 } | |
50 | |
51 // The packets queue for most recently expirect connection. | |
52 BufferedPacketList last_expired_packet_queue_; | |
53 }; | |
54 | |
55 class QuicBufferedPacketStoreTest : public ::testing::Test { | |
56 public: | |
57 QuicBufferedPacketStoreTest() | |
58 : store_(&visitor_, &clock_, &alarm_factory_), | |
59 server_address_(Loopback6(), 65535), | |
60 client_address_(Loopback6(), 65535), | |
61 packet_content_("some encrypted content"), | |
62 packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)), | |
63 data_packet_(packet_content_.data(), | |
64 packet_content_.size(), | |
65 packet_time_) {} | |
66 | |
67 protected: | |
68 QuicBufferedPacketStoreVisitor visitor_; | |
69 MockClock clock_; | |
70 MockAlarmFactory alarm_factory_; | |
71 QuicBufferedPacketStore store_; | |
72 IPEndPoint server_address_; | |
73 IPEndPoint client_address_; | |
74 string packet_content_; | |
75 QuicTime packet_time_; | |
76 QuicReceivedPacket data_packet_; | |
77 }; | |
78 | |
79 TEST_F(QuicBufferedPacketStoreTest, SimpleEnqueueAndDeliverPacket) { | |
80 QuicConnectionId connection_id = 1; | |
81 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
82 client_address_); | |
83 EXPECT_TRUE(store_.HasBufferedPackets(connection_id)); | |
84 list<BufferedPacket> queue = store_.DeliverPackets(connection_id); | |
85 ASSERT_EQ(1u, queue.size()); | |
86 // Check content of the only packet in the queue. | |
87 EXPECT_EQ(packet_content_, queue.front().packet->AsStringPiece()); | |
88 EXPECT_EQ(packet_time_, queue.front().packet->receipt_time()); | |
89 EXPECT_EQ(client_address_, queue.front().client_address); | |
90 EXPECT_EQ(server_address_, queue.front().server_address); | |
91 // No more packets on connection 1 should remain in the store. | |
92 EXPECT_TRUE(store_.DeliverPackets(connection_id).empty()); | |
93 EXPECT_FALSE(store_.HasBufferedPackets(connection_id)); | |
94 } | |
95 | |
96 TEST_F(QuicBufferedPacketStoreTest, DifferentPacketAddressOnOneConnection) { | |
97 IPEndPoint addr_with_new_port(Loopback4(), 256); | |
98 QuicConnectionId connection_id = 1; | |
99 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
100 client_address_); | |
101 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
102 addr_with_new_port); | |
103 list<BufferedPacket> queue = store_.DeliverPackets(connection_id); | |
104 ASSERT_EQ(2u, queue.size()); | |
105 // The address migration path should be preserved. | |
106 EXPECT_EQ(client_address_, queue.front().client_address); | |
107 EXPECT_EQ(addr_with_new_port, queue.back().client_address); | |
108 } | |
109 | |
110 TEST_F(QuicBufferedPacketStoreTest, | |
111 EnqueueAndDeliverMultiplePacketsOnMultipleConnections) { | |
112 size_t num_connections = 10; | |
113 for (QuicConnectionId connection_id = 1; connection_id <= num_connections; | |
114 ++connection_id) { | |
115 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
116 client_address_); | |
117 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
118 client_address_); | |
119 } | |
120 | |
121 // Deliver packets in reversed order. | |
122 for (QuicConnectionId connection_id = num_connections; connection_id > 0; | |
123 --connection_id) { | |
124 list<BufferedPacket> queue = store_.DeliverPackets(connection_id); | |
125 ASSERT_EQ(2u, queue.size()); | |
126 } | |
127 } | |
128 | |
129 TEST_F(QuicBufferedPacketStoreTest, | |
130 FailToBufferTooManyPacketsOnExistingConnection) { | |
131 // Tests that for one connection, only limited number of packets can be | |
132 // buffered. | |
133 size_t num_packets = kDefaultMaxUndecryptablePackets + 1; | |
134 QuicConnectionId connection_id = 1; | |
135 for (size_t i = 1; i <= num_packets; ++i) { | |
136 // Only first |kDefaultMaxUndecryptablePackets packets| will be buffered. | |
137 EnqueuePacketResult result = store_.EnqueuePacket( | |
138 connection_id, data_packet_, server_address_, client_address_); | |
139 if (i <= kDefaultMaxUndecryptablePackets) { | |
140 EXPECT_EQ(EnqueuePacketResult::SUCCESS, result); | |
141 } else { | |
142 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_PACKETS, result); | |
143 } | |
144 } | |
145 | |
146 // Only first |kDefaultMaxUndecryptablePackets| packets are kept in the store | |
147 // and can be delivered. | |
148 EXPECT_EQ(kDefaultMaxUndecryptablePackets, | |
149 store_.DeliverPackets(connection_id).size()); | |
150 } | |
151 | |
152 TEST_F(QuicBufferedPacketStoreTest, FailToBufferPacketsForTooManyConnections) { | |
153 // Tests that store can only keep early arrived packets for limited number of | |
154 // connections. | |
155 size_t num_connections = kDefaultMaxConnectionsInStore + 1; | |
156 for (size_t connection_id = 1; connection_id <= num_connections; | |
157 ++connection_id) { | |
158 EnqueuePacketResult result = store_.EnqueuePacket( | |
159 connection_id, data_packet_, server_address_, client_address_); | |
160 if (connection_id <= kDefaultMaxConnectionsInStore) { | |
161 EXPECT_EQ(EnqueuePacketResult::SUCCESS, result); | |
162 } else { | |
163 EXPECT_EQ(EnqueuePacketResult::TOO_MANY_CONNECTIONS, result); | |
164 } | |
165 } | |
166 // Store only keeps early arrived packets upto |kDefaultMaxConnectionsInStore| | |
167 // connections. | |
168 for (size_t connection_id = 1; connection_id <= num_connections; | |
169 ++connection_id) { | |
170 list<BufferedPacket> queue = store_.DeliverPackets(connection_id); | |
171 if (connection_id <= kDefaultMaxConnectionsInStore) { | |
172 EXPECT_EQ(1u, queue.size()); | |
173 } else { | |
174 EXPECT_EQ(0u, queue.size()); | |
175 } | |
176 } | |
177 } | |
178 | |
179 TEST_F(QuicBufferedPacketStoreTest, PacketQueueExpiredBeforeDelivery) { | |
180 QuicConnectionId connection_id = 1; | |
181 store_.EnqueuePacket(connection_id, data_packet_, server_address_, | |
182 client_address_); | |
183 // Packet for another connection arrive 1ms later. | |
184 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); | |
185 QuicConnectionId connection_id2 = 2; | |
186 // Use different client address to differetiate packets from different | |
187 // connections. | |
188 IPEndPoint another_client_address(Loopback4(), 255); | |
189 store_.EnqueuePacket(connection_id2, data_packet_, server_address_, | |
190 another_client_address); | |
191 // Advance clock to the time when connection 1 expires. | |
192 clock_.AdvanceTime( | |
193 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() - | |
194 clock_.ApproximateNow()); | |
195 ASSERT_GE(clock_.ApproximateNow(), | |
196 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline()); | |
197 // Fire alarm to remove long-staying connection 1 packets. | |
198 alarm_factory_.FireAlarm( | |
199 QuicBufferedPacketStorePeer::expiration_alarm(&store_)); | |
200 EXPECT_EQ(1u, visitor_.last_expired_packet_queue_.buffered_packets.size()); | |
201 // Try to deliver packets, but packet queue has been removed so no | |
202 // packets can be returned. | |
203 ASSERT_EQ(0u, store_.DeliverPackets(connection_id).size()); | |
204 | |
205 // Deliver packets on connection 2. And the queue for connection 2 should be | |
206 // returned. | |
207 list<BufferedPacket> queue = store_.DeliverPackets(connection_id2); | |
208 ASSERT_EQ(1u, queue.size()); | |
209 // Packets in connection 2 should use another client address. | |
210 EXPECT_EQ(another_client_address, queue.front().client_address); | |
211 | |
212 // Test the alarm is reset by enqueueing 2 packets for 3rd connection and wait | |
213 // for them to expire. | |
214 QuicConnectionId connection_id3 = 3; | |
215 store_.EnqueuePacket(connection_id3, data_packet_, server_address_, | |
216 client_address_); | |
217 store_.EnqueuePacket(connection_id3, data_packet_, server_address_, | |
218 client_address_); | |
219 clock_.AdvanceTime( | |
220 QuicBufferedPacketStorePeer::expiration_alarm(&store_)->deadline() - | |
221 clock_.ApproximateNow()); | |
222 alarm_factory_.FireAlarm( | |
223 QuicBufferedPacketStorePeer::expiration_alarm(&store_)); | |
224 // |last_expired_packet_queue_| should be updated. | |
225 EXPECT_EQ(2u, visitor_.last_expired_packet_queue_.buffered_packets.size()); | |
226 } | |
227 | |
228 } // namespace | |
229 } // namespace test | |
230 } // namespace net | |
OLD | NEW |