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

Unified Diff: net/tools/quic/quic_dispatcher_test.cc

Issue 2236973002: Landing Recent QUIC changes until 4AM, Aug 7, 2016 UTC-4 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: flip quic_sequencer_buffer_retire_block_in_time to true Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_packet_printer_bin.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/quic/quic_dispatcher_test.cc
diff --git a/net/tools/quic/quic_dispatcher_test.cc b/net/tools/quic/quic_dispatcher_test.cc
index 967474df0d683b0f8a1e6a1294a13c3271cb60c4..07df1e6830971a8b8d0c5a2ec7bb0a93bdfba742 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -9,7 +9,7 @@
#include <string>
#include "base/macros.h"
-#include "base/strings/string_piece.h"
+#include "base/strings/string_number_conversions.h"
#include "net/quic/core/crypto/crypto_handshake.h"
#include "net/quic/core/crypto/quic_crypto_server_config.h"
#include "net/quic/core/crypto/quic_random.h"
@@ -17,18 +17,24 @@
#include "net/quic/core/quic_flags.h"
#include "net/quic/core/quic_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/quic_buffered_packet_store_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/test/gtest_util.h"
#include "net/tools/epoll_server/epoll_server.h"
+#include "net/tools/quic/chlo_extractor.h"
#include "net/tools/quic/quic_epoll_alarm_factory.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_packet_writer_wrapper.h"
#include "net/tools/quic/quic_simple_server_session_helper.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
+#include "net/tools/quic/stateless_rejector.h"
#include "net/tools/quic/test_tools/mock_quic_time_wait_list_manager.h"
#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gmock_mutant.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::IntToString;
using base::StringPiece;
using net::EpollServer;
using net::test::ConstructEncryptedPacket;
@@ -36,14 +42,18 @@ using net::test::CryptoTestUtils;
using net::test::MockQuicConnection;
using net::test::MockQuicConnectionHelper;
using net::test::ValueRestore;
+using std::ostream;
using std::string;
using std::vector;
+using testing::CreateFunctor;
using testing::DoAll;
using testing::InSequence;
using testing::Invoke;
using testing::WithoutArgs;
using testing::_;
+static const size_t kDefaultMaxConnectionsInStore = 100;
+
namespace net {
namespace test {
namespace {
@@ -61,7 +71,8 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
crypto_config,
compressed_certs_cache),
crypto_stream_(QuicServerSessionBase::GetCryptoStream()) {}
- ~TestQuicSpdyServerSession() override{};
+
+ ~TestQuicSpdyServerSession() override { delete connection(); };
MOCK_METHOD3(OnConnectionClosed,
void(QuicErrorCode error,
@@ -114,6 +125,8 @@ class TestDispatcher : public QuicDispatcher {
QuicServerSessionBase*(QuicConnectionId connection_id,
const IPEndPoint& client_address));
+ MOCK_METHOD1(OnNewConnectionAdded, void(QuicConnectionId connection_id));
+
using QuicDispatcher::current_server_address;
using QuicDispatcher::current_client_address;
};
@@ -144,36 +157,12 @@ class MockServerConnection : public MockQuicConnection {
QuicDispatcher* dispatcher_;
};
-QuicServerSessionBase* CreateSession(
- QuicDispatcher* dispatcher,
- const QuicConfig& config,
- QuicConnectionId connection_id,
- const IPEndPoint& client_address,
- MockQuicConnectionHelper* helper,
- MockAlarmFactory* alarm_factory,
- const QuicCryptoServerConfig* crypto_config,
- QuicCompressedCertsCache* compressed_certs_cache,
- TestQuicSpdyServerSession** session) {
- MockServerConnection* connection = new MockServerConnection(
- connection_id, helper, alarm_factory, dispatcher);
- *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
- compressed_certs_cache);
- connection->set_visitor(*session);
- ON_CALL(*connection, CloseConnection(_, _, _))
- .WillByDefault(WithoutArgs(Invoke(
- connection, &MockServerConnection::UnregisterOnConnectionClosed)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>((*session)->connection()),
- ProcessUdpPacket(_, client_address, _));
-
- return *session;
-}
-
class QuicDispatcherTest : public ::testing::Test {
public:
QuicDispatcherTest()
: helper_(&eps_, QuicAllocator::BUFFER_POOL),
alarm_factory_(&eps_),
- version_manager_(QuicSupportedVersions()),
+ version_manager_(AllSupportedVersions()),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
CryptoTestUtils::ProofSourceForTesting()),
@@ -183,7 +172,10 @@ class QuicDispatcherTest : public ::testing::Test {
&eps_)),
time_wait_list_manager_(nullptr),
session1_(nullptr),
- session2_(nullptr) {
+ session2_(nullptr),
+ store_(nullptr) {}
+
+ void SetUp() override {
dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1));
}
@@ -235,8 +227,8 @@ class QuicDispatcherTest : public ::testing::Test {
QuicPathId path_id,
QuicPacketNumber packet_number) {
ProcessPacket(client_address, connection_id, has_version_flag,
- QuicSupportedVersions().front(), data, connection_id_length,
- packet_number_length, packet_number);
+ CurrentSupportedVersions().front(), data,
+ connection_id_length, packet_number_length, packet_number);
}
// Processes a packet.
@@ -255,14 +247,47 @@ class QuicDispatcherTest : public ::testing::Test {
std::unique_ptr<QuicReceivedPacket> received_packet(
ConstructReceivedPacket(*packet, helper_.GetClock()->Now()));
- data_ = string(packet->data(), packet->length());
+ if (ChloExtractor::Extract(*packet, versions, nullptr)) {
+ // Add CHLO packet to the beginning to be verified first, because it is
+ // also processed first by new session.
+ data_connection_map_[connection_id].push_front(
+ string(packet->data(), packet->length()));
+ } else {
+ // For non-CHLO, always append to last.
+ data_connection_map_[connection_id].push_back(
+ string(packet->data(), packet->length()));
+ }
dispatcher_->ProcessPacket(server_address_, client_address,
*received_packet);
}
- void ValidatePacket(const QuicEncryptedPacket& packet) {
- EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
- EXPECT_EQ(data_, packet.AsStringPiece());
+ void ValidatePacket(QuicConnectionId conn_id,
+ const QuicEncryptedPacket& packet) {
+ EXPECT_EQ(data_connection_map_[conn_id].front().length(),
+ packet.AsStringPiece().length());
+ EXPECT_EQ(data_connection_map_[conn_id].front(), packet.AsStringPiece());
+ data_connection_map_[conn_id].pop_front();
+ }
+
+ QuicServerSessionBase* CreateSession(
+ QuicDispatcher* dispatcher,
+ const QuicConfig& config,
+ QuicConnectionId connection_id,
+ const IPEndPoint& client_address,
+ MockQuicConnectionHelper* helper,
+ MockAlarmFactory* alarm_factory,
+ const QuicCryptoServerConfig* crypto_config,
+ QuicCompressedCertsCache* compressed_certs_cache,
+ TestQuicSpdyServerSession** session) {
+ MockServerConnection* connection = new MockServerConnection(
+ connection_id, helper, alarm_factory, dispatcher);
+ *session = new TestQuicSpdyServerSession(config, connection, crypto_config,
+ compressed_certs_cache);
+ connection->set_visitor(*session);
+ ON_CALL(*connection, CloseConnection(_, _, _))
+ .WillByDefault(WithoutArgs(Invoke(
+ connection, &MockServerConnection::UnregisterOnConnectionClosed)));
+ return *session;
}
void CreateTimeWaitListManager() {
@@ -293,7 +318,8 @@ class QuicDispatcherTest : public ::testing::Test {
MockTimeWaitListManager* time_wait_list_manager_;
TestQuicSpdyServerSession* session1_;
TestQuicSpdyServerSession* session2_;
- string data_;
+ std::map<QuicConnectionId, std::list<string>> data_connection_map_;
+ QuicBufferedPacketStore* store_;
};
TEST_F(QuicDispatcherTest, ProcessPackets) {
@@ -305,6 +331,10 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
dispatcher_.get(), config_, 1, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
ProcessPacket(client_address, 1, true, false, SerializeCHLO());
EXPECT_EQ(client_address, dispatcher_->current_client_address());
EXPECT_EQ(server_address_, dispatcher_->current_server_address());
@@ -314,13 +344,17 @@ TEST_F(QuicDispatcherTest, ProcessPackets) {
dispatcher_.get(), config_, 2, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 2))));
ProcessPacket(client_address, 2, true, false, SerializeCHLO());
EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.Times(1)
- .WillOnce(testing::WithArgs<2>(
- Invoke(this, &QuicDispatcherTest::ValidatePacket)));
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
ProcessPacket(client_address, 1, false, false, "data");
}
@@ -342,6 +376,10 @@ TEST_F(QuicDispatcherTest, Shutdown) {
dispatcher_.get(), config_, 1, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
ProcessPacket(client_address, 1, true, false, SerializeCHLO());
@@ -362,6 +400,11 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
dispatcher_.get(), config_, connection_id, client_address,
&mock_helper_, &mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
+
ProcessPacket(client_address, connection_id, true, false, SerializeCHLO());
// Close the connection by sending public reset packet.
@@ -439,6 +482,10 @@ TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
dispatcher_.get(), config_, 1, client_address, &mock_helper_,
&mock_alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
// A packet whose packet number is the largest that is allowed to start a
// connection.
ProcessPacket(client_address, connection_id, true, false, SerializeCHLO(),
@@ -535,7 +582,8 @@ class QuicDispatcherStatelessRejectTest
: public QuicDispatcherTest,
public ::testing::WithParamInterface<StatelessRejectTestParams> {
public:
- QuicDispatcherStatelessRejectTest() : crypto_stream1_(nullptr) {}
+ QuicDispatcherStatelessRejectTest()
+ : QuicDispatcherTest(), crypto_stream1_(nullptr) {}
~QuicDispatcherStatelessRejectTest() override {
if (crypto_stream1_) {
@@ -546,6 +594,7 @@ class QuicDispatcherStatelessRejectTest
// This test setup assumes that all testing will be done using
// crypto_stream1_.
void SetUp() override {
+ QuicDispatcherTest::SetUp();
FLAGS_enable_quic_stateless_reject_support =
GetParam().enable_stateless_rejects_via_flag;
}
@@ -596,7 +645,11 @@ TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(
CreateSessionBasedOnTestParams(connection_id, client_address)));
-
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
// Process the first packet for the connection.
ProcessPacket(client_address, connection_id, true, false, SerializeCHLO());
if (ExpectStatelessReject()) {
@@ -622,13 +675,15 @@ TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
ProcessUdpPacket(_, _, _))
.Times(1)
.WillOnce(testing::WithArgs<2>(
- Invoke(this, &QuicDispatcherTest::ValidatePacket)));
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
}
ProcessPacket(client_address, connection_id, true, false, "data");
}
TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
FLAGS_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_buffer_packet_till_chlo = true;
CreateTimeWaitListManager();
IPEndPoint client_address(net::test::Loopback4(), 1);
@@ -640,6 +695,10 @@ TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(
CreateSessionBasedOnTestParams(connection_id, client_address)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
}
VLOG(1) << "ExpectStatelessReject: " << ExpectStatelessReject();
@@ -668,20 +727,41 @@ TEST_P(QuicDispatcherStatelessRejectTest, CheapRejects) {
TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) {
FLAGS_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_always_log_bugs_for_tests = true;
CreateTimeWaitListManager();
const IPEndPoint client_address(net::test::Loopback4(), 1);
const QuicConnectionId connection_id = 1;
- if (!GetParam().enable_stateless_rejects_via_flag) {
- // If stateless rejects are not being used, then a connection will be
- // created immediately.
+ if (!GetParam().enable_stateless_rejects_via_flag &&
+ !FLAGS_quic_buffer_packet_till_chlo) {
+ // If stateless rejects are not being used and early arrived packets are not
+ // buffered, then a connection will be created immediately.
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(
CreateSessionBasedOnTestParams(connection_id, client_address)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, client_address, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ }
+ bool first_packet_dropped = GetParam().enable_stateless_rejects_via_flag &&
+ !FLAGS_quic_buffer_packet_till_chlo;
+ if (first_packet_dropped) {
+ // Never do stateless reject while
+ // FLAGS_quic_buffer_packet_till_chlo is off.
+ EXPECT_DFATAL(
+ ProcessPacket(client_address, connection_id, true, false,
+ "NOT DATA FOR A CHLO"),
+ "Have to drop packet because buffering non-chlo packet is "
+ "not supported while trying to do stateless reject. "
+ "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false "
+ "--gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true");
+ } else {
+ ProcessPacket(client_address, connection_id, true, false,
+ "NOT DATA FOR A CHLO");
}
- ProcessPacket(client_address, connection_id, true, false,
- "NOT DATA FOR A CHLO");
// Process the first packet for the connection.
// clang-format off
@@ -695,16 +775,33 @@ TEST_P(QuicDispatcherStatelessRejectTest, BufferNonChlo) {
nullptr);
// clang-format on
- if (GetParam().enable_stateless_rejects_via_flag) {
+ if (GetParam().enable_stateless_rejects_via_flag ||
+ FLAGS_quic_buffer_packet_till_chlo) {
// If stateless rejects are enabled then a connection will be created now
// and the buffered packet will be processed
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address))
.WillOnce(testing::Return(
CreateSessionBasedOnTestParams(connection_id, client_address)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, client_address, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))));
+ }
+ if (!first_packet_dropped) {
+ // Expect both packets to be passed to ProcessUdpPacket(). And one of them
+ // is already expected in CreateSessionBasedOnTestParams().
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, client_address, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), connection_id))))
+ .RetiresOnSaturation();
+ } else {
+ // Since first packet is dropped, remove it from map to skip
+ // ValidatePacket() on it.
+ data_connection_map_[connection_id].pop_front();
}
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, client_address, _))
- .RetiresOnSaturation();
ProcessPacket(client_address, connection_id, true, false,
client_hello.GetSerialized().AsStringPiece().as_string());
EXPECT_FALSE(
@@ -758,6 +855,7 @@ class BlockingWriter : public QuicPacketWriterWrapper {
class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
public:
void SetUp() override {
+ QuicDispatcherTest::SetUp();
writer_ = new BlockingWriter;
QuicDispatcherPeer::UseWriter(dispatcher_.get(), writer_);
@@ -768,6 +866,10 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
dispatcher_.get(), config_, 1, client_address, &helper_,
&alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 1))));
ProcessPacket(client_address, 1, true, false, SerializeCHLO());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, client_address))
@@ -775,6 +877,10 @@ class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
dispatcher_.get(), config_, 2, client_address, &helper_,
&alarm_factory_, &crypto_config_,
QuicDispatcherPeer::GetCache(dispatcher_.get()), &session2_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session2_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArgs<2>(Invoke(CreateFunctor(
+ &QuicDispatcherTest::ValidatePacket, base::Unretained(this), 2))));
ProcessPacket(client_address, 2, true, false, SerializeCHLO());
blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(dispatcher_.get());
@@ -931,6 +1037,251 @@ TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
EXPECT_FALSE(dispatcher_->HasPendingWrites());
}
+// Tests that bufferring packets works in stateful reject, expensive stateless
+// reject and cheap stateless reject.
+struct BufferedPacketStoreTestParams {
+ BufferedPacketStoreTestParams(bool enable_stateless_rejects_via_flag,
+ bool support_cheap_stateless_reject)
+ : enable_stateless_rejects_via_flag(enable_stateless_rejects_via_flag),
+ support_cheap_stateless_reject(support_cheap_stateless_reject) {}
+
+ friend ostream& operator<<(ostream& os,
+ const BufferedPacketStoreTestParams& p) {
+ os << "{ enable_stateless_rejects_via_flag: "
+ << p.enable_stateless_rejects_via_flag << std::endl;
+ os << " support_cheap_stateless_reject: "
+ << p.support_cheap_stateless_reject << " }";
+ return os;
+ }
+
+ // This only enables the stateless reject feature via the feature-flag.
+ // This should be a no-op if the peer does not support them.
+ bool enable_stateless_rejects_via_flag;
+ // Whether to do cheap stateless or not.
+ bool support_cheap_stateless_reject;
+};
+
+vector<BufferedPacketStoreTestParams> GetBufferedPacketStoreTestParams() {
+ vector<BufferedPacketStoreTestParams> params;
+ for (bool enable_stateless_rejects_via_flag : {true, false}) {
+ for (bool support_cheap_stateless_reject : {true, false}) {
+ params.push_back(BufferedPacketStoreTestParams(
+ enable_stateless_rejects_via_flag, support_cheap_stateless_reject));
+ }
+ }
+ return params;
+}
+
+// A dispatcher whose stateless rejector will always ACCEPTs CHLO.
+class BufferedPacketStoreTest
+ : public QuicDispatcherTest,
+ public ::testing::WithParamInterface<BufferedPacketStoreTestParams> {
+ public:
+ BufferedPacketStoreTest()
+ : QuicDispatcherTest(), client_addr_(Loopback4(), 1234) {
+ FLAGS_quic_buffer_packet_till_chlo = true;
+ FLAGS_quic_use_cheap_stateless_rejects =
+ GetParam().support_cheap_stateless_reject;
+ FLAGS_enable_quic_stateless_reject_support =
+ GetParam().enable_stateless_rejects_via_flag;
+ }
+
+ void SetUp() override {
+ QuicDispatcherTest::SetUp();
+ clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
+
+ QuicVersion version = AllSupportedVersions().front();
+ CryptoHandshakeMessage chlo = CryptoTestUtils::GenerateDefaultInchoateCHLO(
+ clock_, version, &crypto_config_);
+ chlo.SetVector(net::kCOPT, net::QuicTagVector{net::kSREJ});
+ // Pass an inchoate CHLO.
+ CryptoTestUtils::GenerateFullCHLO(
+ chlo, &crypto_config_, server_ip_, client_addr_, version, clock_,
+ &proof_, QuicDispatcherPeer::GetCache(dispatcher_.get()), &full_chlo_);
+ }
+
+ string SerializeFullCHLO() {
+ return full_chlo_.GetSerialized().AsStringPiece().as_string();
+ }
+
+ protected:
+ IPAddress server_ip_;
+ IPEndPoint client_addr_;
+ QuicCryptoProof proof_;
+ const QuicClock* clock_;
+ CryptoHandshakeMessage full_chlo_;
+};
+
+INSTANTIATE_TEST_CASE_P(
+ BufferedPacketStoreTests,
+ BufferedPacketStoreTest,
+ ::testing::ValuesIn(GetBufferedPacketStoreTestParams()));
+
+TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
+ InSequence s;
+ IPEndPoint client_address(Loopback4(), 1);
+ server_address_ = IPEndPoint(Any4(), 5);
+ QuicConnectionId conn_id = 1;
+ // A bunch of non-CHLO should be buffered upon arrival, and the first one
+ // should trigger OnNewConnectionAdded().
+ EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id)).Times(1);
+ for (size_t i = 1; i <= kDefaultMaxUndecryptablePackets + 1; ++i) {
+ ProcessPacket(client_address, conn_id, true, false,
+ "data packet " + IntToString(i + 1),
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+ kDefaultPathId,
+ /*packet_number=*/i + 1);
+ }
+ EXPECT_EQ(0u, dispatcher_->session_map().size())
+ << "No session should be created before CHLO arrives.";
+
+ // Pop out the last packet as it is also be dropped by the store.
+ data_connection_map_[conn_id].pop_back();
+ // When CHLO arrives, a new session should be created, and all packets
+ // buffered should be delivered to the session.
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
+ &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+
+ // Only |kDefaultMaxUndecryptablePackets| packets were buffered, and they
+ // should be delivered in arrival order.
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .Times(kDefaultMaxUndecryptablePackets + 1) // + 1 for CHLO.
+ .WillRepeatedly(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+}
+
+TEST_P(BufferedPacketStoreTest,
+ ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
+ InSequence s;
+ server_address_ = IPEndPoint(Any4(), 5);
+ // A bunch of non-CHLO should be buffered upon arrival.
+ for (size_t i = 1; i <= kDefaultMaxConnectionsInStore + 1; ++i) {
+ IPEndPoint client_address(Loopback4(), i);
+ QuicConnectionId conn_id = i;
+ if (i <= kDefaultMaxConnectionsInStore) {
+ // As they are on different connection, they should trigger
+ // OnNewConnectionAdded(). The last packet should be dropped.
+ EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id));
+ }
+ ProcessPacket(client_address, conn_id, true, false,
+ "data packet on connection " + IntToString(i),
+ PACKET_8BYTE_CONNECTION_ID, PACKET_6BYTE_PACKET_NUMBER,
+ kDefaultPathId,
+ /*packet_number=*/2);
+ }
+
+ // Pop out the packet on last connection as it shouldn't be enqueued in store
+ // as well.
+ data_connection_map_[kDefaultMaxConnectionsInStore + 1].pop_front();
+
+ // Process CHLOs.
+ for (size_t i = 1; i <= kDefaultMaxConnectionsInStore + 1; ++i) {
+ IPEndPoint client_address(Loopback4(), i);
+ QuicConnectionId conn_id = i;
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
+ &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ if (conn_id == kDefaultMaxConnectionsInStore + 1) {
+ // The last CHLO should trigger OnNewConnectionAdded() since it's the
+ // first packet arrives on that connection.
+ EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id));
+ }
+ // First |kDefaultMaxConnectionsInStore| connections should have buffered
+ // a packet in store. The rest should have been dropped.
+ if (i <= kDefaultMaxConnectionsInStore) {
+ EXPECT_CALL(
+ *reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, client_address, _))
+ .Times(2)
+ .WillRepeatedly(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+ }
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+ }
+}
+
+// Tests that store delivers empty packet list if CHLO arrives firstly.
+TEST_P(BufferedPacketStoreTest, DeliverEmptyPackets) {
+ QuicConnectionId conn_id = 1;
+ IPEndPoint client_address(Loopback4(), 1);
+ EXPECT_CALL(*dispatcher_, OnNewConnectionAdded(conn_id));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
+ &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+}
+
+// Tests that by the time a retransmitted CHLO arrives, a connection for the
+// CHLO should already be created.
+TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
+ InSequence s;
+ IPEndPoint client_address(Loopback4(), 1);
+ server_address_ = IPEndPoint(Any4(), 5);
+ QuicConnectionId conn_id = 1;
+ ProcessPacket(client_address, conn_id, true, false,
+ "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId,
+ /*packet_number=*/2);
+
+ // When CHLO arrives, a new session should be created, and all packets
+ // buffered should be delivered to the session.
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_address))
+ .Times(1) // Only triggered by 1st CHLO.
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, conn_id, client_address, &mock_helper_,
+ &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .Times(3) // Triggered by 1 data packet and 2 CHLOs.
+ .WillRepeatedly(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+}
+
+// Tests that expiration of a connection add connection id to time wait list.
+TEST_P(BufferedPacketStoreTest, ReceiveCHLOAfterExpiration) {
+ InSequence s;
+ CreateTimeWaitListManager();
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+ QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
+
+ IPEndPoint client_address(Loopback4(), 1);
+ server_address_ = IPEndPoint(Any4(), 5);
+ QuicConnectionId conn_id = 1;
+ ProcessPacket(client_address, conn_id, true, false,
+ "data packet " + IntToString(2), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_6BYTE_PACKET_NUMBER, kDefaultPathId,
+ /*packet_number=*/2);
+
+ mock_helper_.AdvanceTime(
+ QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
+ QuicAlarm* alarm = QuicBufferedPacketStorePeer::expiration_alarm(store);
+ // Cancel alarm as if it had been fired.
+ alarm->Cancel();
+ store->OnExpirationTimeout();
+ // New arrived CHLO will be dropped because this connection is in time wait
+ // list.
+ ASSERT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+ EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, conn_id, _, _));
+ ProcessPacket(client_address, conn_id, true, false, SerializeFullCHLO());
+}
+
} // namespace
} // namespace test
} // namespace net
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_packet_printer_bin.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698