| 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 |