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

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

Issue 2430973004: Landing Recent QUIC changes until 10:38 AM, Oct 17, 2016 UTC-4 (Closed)
Patch Set: Improving flagsaver logging Created 4 years, 2 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_simple_server_stream.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 85712d62fac61f49e4a67b411b52457c077bda02..62d7b4238d31829d814f991382f5d7b7bf61d9ea 100644
--- a/net/tools/quic/quic_dispatcher_test.cc
+++ b/net/tools/quic/quic_dispatcher_test.cc
@@ -17,8 +17,11 @@
#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/fake_proof_source.h"
#include "net/quic/test_tools/quic_buffered_packet_store_peer.h"
+#include "net/quic/test_tools/quic_crypto_server_config_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/quic/test_tools/quic_time_wait_list_manager_peer.h"
#include "net/test/gtest_util.h"
#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/chlo_extractor.h"
@@ -169,12 +172,15 @@ class MockServerConnection : public MockQuicConnection {
class QuicDispatcherTest : public ::testing::Test {
public:
QuicDispatcherTest()
+ : QuicDispatcherTest(CryptoTestUtils::ProofSourceForTesting()) {}
+
+ explicit QuicDispatcherTest(std::unique_ptr<ProofSource> proof_source)
: helper_(&eps_, QuicAllocator::BUFFER_POOL),
alarm_factory_(&eps_),
version_manager_(AllSupportedVersions()),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance(),
- CryptoTestUtils::ProofSourceForTesting()),
+ std::move(proof_source)),
dispatcher_(new TestDispatcher(config_,
&crypto_config_,
&version_manager_,
@@ -1218,6 +1224,9 @@ TEST_P(BufferedPacketStoreTest,
QuicConnectionId conn_id = i;
if (FLAGS_quic_create_session_after_insertion &&
conn_id == kNumConnections) {
+ // The last CHLO should trigger ShouldCreateOrBufferPacketForConnection()
+ // since it's the
+ // first packet arrives on that connection.
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(conn_id));
}
@@ -1531,6 +1540,491 @@ TEST_P(BufferedPacketStoreTest, ReceiveCHLOForBufferedConnection) {
EXPECT_TRUE(store->HasChloForConnection(/*connection_id=*/1));
}
+// Test which exercises the async GetProof codepaths, especially in the context
+// of stateless rejection.
+class AsyncGetProofTest : public QuicDispatcherTest {
+ public:
+ AsyncGetProofTest()
+ : QuicDispatcherTest(
+ std::unique_ptr<FakeProofSource>(new FakeProofSource())),
+ client_addr_(net::test::Loopback4(), 1234),
+ crypto_config_peer_(&crypto_config_) {
+ FLAGS_enable_async_get_proof = true;
+ FLAGS_quic_buffer_packet_till_chlo = true;
+ FLAGS_enable_quic_stateless_reject_support = true;
+ FLAGS_quic_use_cheap_stateless_rejects = true;
+ FLAGS_quic_create_session_after_insertion = true;
+ }
+
+ void SetUp() override {
+ QuicDispatcherTest::SetUp();
+
+ clock_ = QuicDispatcherPeer::GetHelper(dispatcher_.get())->GetClock();
+ QuicVersion version = AllSupportedVersions().front();
+ 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_);
+
+ GetFakeProofSource()->Activate();
+ }
+
+ FakeProofSource* GetFakeProofSource() const {
+ return static_cast<FakeProofSource*>(crypto_config_peer_.GetProofSource());
+ }
+
+ string SerializeFullCHLO() {
+ return full_chlo_.GetSerialized().AsStringPiece().as_string();
+ }
+
+ string SerializeCHLO() {
+ return chlo_.GetSerialized().AsStringPiece().as_string();
+ }
+
+ // Sets up a session, and crypto stream based on the test parameters.
+ QuicServerSessionBase* GetSession(QuicConnectionId connection_id) {
+ auto it = sessions_.find(connection_id);
+ if (it != sessions_.end()) {
+ return it->second.session;
+ }
+
+ TestQuicSpdyServerSession* session;
+ CreateSession(dispatcher_.get(), config_, connection_id, client_addr_,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session);
+
+ std::unique_ptr<MockQuicCryptoServerStream> crypto_stream(
+ new MockQuicCryptoServerStream(
+ crypto_config_, QuicDispatcherPeer::GetCache(dispatcher_.get()),
+ session, session->stream_helper()));
+ session->SetCryptoStream(crypto_stream.get());
+ crypto_stream->SetPeerSupportsStatelessRejects(true);
+ const bool ok =
+ sessions_
+ .insert(std::make_pair(
+ connection_id, SessionInfo{session, std::move(crypto_stream)}))
+ .second;
+ CHECK(ok);
+ return session;
+ }
+
+ protected:
+ const IPEndPoint client_addr_;
+
+ private:
+ QuicCryptoServerConfigPeer crypto_config_peer_;
+ IPAddress server_ip_;
+ QuicCryptoProof proof_;
+ const QuicClock* clock_;
+ CryptoHandshakeMessage chlo_;
+ CryptoHandshakeMessage full_chlo_;
+
+ struct SessionInfo {
+ TestQuicSpdyServerSession* session;
+ std::unique_ptr<MockQuicCryptoServerStream> crypto_stream;
+ };
+ std::map<QuicConnectionId, SessionInfo> sessions_;
+};
+
+// Test a simple situation of connections which the StatelessRejector will
+// accept.
+TEST_F(AsyncGetProofTest, BasicAccept) {
+ QuicConnectionId conn_id = 1;
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_))
+ .WillOnce(testing::Return(GetSession(conn_id)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+ }
+
+ // Send a CHLO that the StatelessRejector will accept.
+ ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ check.Call(1);
+ // Complete the ProofSource::GetProof call and verify that a session is
+ // created.
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+
+ check.Call(2);
+ // Verify that a data packet gets processed immediately.
+ ProcessPacket(client_addr_, conn_id, true, false, "My name is Data");
+}
+
+// Test a simple situation of connections which the StatelessRejector will
+// reject.
+TEST_F(AsyncGetProofTest, BasicReject) {
+ CreateTimeWaitListManager();
+
+ QuicConnectionId conn_id = 1;
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(conn_id, _, true, _));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id, _, _));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id, _, _));
+ }
+
+ // Send a CHLO that the StatelessRejector will reject.
+ ProcessPacket(client_addr_, conn_id, true, false, SerializeCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ // Complete the ProofSource::GetProof call and verify that the connection and
+ // packet are processed by the time wait list manager.
+ check.Call(1);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+
+ // Verify that a data packet is passed to the time wait list manager.
+ check.Call(2);
+ ProcessPacket(client_addr_, conn_id, true, false, "My name is Data");
+}
+
+// Test a situation with multiple interleaved connections which the
+// StatelessRejector will accept.
+TEST_F(AsyncGetProofTest, MultipleAccept) {
+ QuicConnectionId conn_id_1 = 1;
+ QuicConnectionId conn_id_2 = 2;
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_,
+ ShouldCreateOrBufferPacketForConnection(conn_id_2));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_))
+ .WillOnce(testing::Return(GetSession(conn_id_2)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id_2)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id_2))));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id_2)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id_2))));
+
+ EXPECT_CALL(check, Call(3));
+ EXPECT_CALL(*dispatcher_,
+ ShouldCreateOrBufferPacketForConnection(conn_id_1));
+
+ EXPECT_CALL(check, Call(4));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_))
+ .WillOnce(testing::Return(GetSession(conn_id_1)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id_1)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillRepeatedly(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id_1))));
+ }
+
+ // Send a CHLO that the StatelessRejector will accept.
+ ProcessPacket(client_addr_, conn_id_1, true, false, SerializeFullCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ // Send another CHLO that the StatelessRejector will accept.
+ ProcessPacket(client_addr_, conn_id_2, true, false, SerializeFullCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
+
+ // Complete the second ProofSource::GetProof call and verify that a session is
+ // created.
+ check.Call(1);
+ GetFakeProofSource()->InvokePendingCallback(1);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ // Verify that a data packet on that connection gets processed immediately.
+ check.Call(2);
+ ProcessPacket(client_addr_, conn_id_2, true, false, "My name is Data");
+
+ // Verify that a data packet on the other connection does not get processed
+ // yet.
+ check.Call(3);
+ ProcessPacket(client_addr_, conn_id_1, true, false, "My name is Data");
+ EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
+
+ // Complete the first ProofSource::GetProof call and verify that a session is
+ // created and the buffered packet is processed.
+ check.Call(4);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+}
+
+// Test a situation with multiple interleaved connections which the
+// StatelessRejector will reject.
+TEST_F(AsyncGetProofTest, MultipleReject) {
+ CreateTimeWaitListManager();
+
+ QuicConnectionId conn_id_1 = 1;
+ QuicConnectionId conn_id_2 = 2;
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(conn_id_2, _, true, _));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id_2, _, _));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id_2, _, _));
+
+ EXPECT_CALL(check, Call(3));
+ EXPECT_CALL(*dispatcher_,
+ ShouldCreateOrBufferPacketForConnection(conn_id_1));
+
+ EXPECT_CALL(check, Call(4));
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(conn_id_1, _, true, _));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id_1, _, _));
+ }
+
+ // Send a CHLO that the StatelessRejector will reject.
+ ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ // Send another CHLO that the StatelessRejector will reject.
+ ProcessPacket(client_addr_, conn_id_2, true, false, SerializeCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
+
+ // Complete the second ProofSource::GetProof call and verify that the
+ // connection and packet are processed by the time wait manager.
+ check.Call(1);
+ GetFakeProofSource()->InvokePendingCallback(1);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+
+ // Verify that a data packet on that connection gets processed immediately by
+ // the time wait manager.
+ check.Call(2);
+ ProcessPacket(client_addr_, conn_id_2, true, false, "My name is Data");
+
+ // Verify that a data packet on the first connection gets buffered.
+ check.Call(3);
+ ProcessPacket(client_addr_, conn_id_1, true, false, "My name is Data");
+ EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
+
+ // Complete the first ProofSource::GetProof call and verify that the CHLO is
+ // processed by the time wait manager and the remaining packets are discarded.
+ check.Call(4);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_2));
+}
+
+// Test a situation with multiple identical CHLOs which the StatelessRejector
+// will reject.
+TEST_F(AsyncGetProofTest, MultipleIdenticalReject) {
+ CreateTimeWaitListManager();
+
+ QuicConnectionId conn_id_1 = 1;
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_,
+ ShouldCreateOrBufferPacketForConnection(conn_id_1));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_1, client_addr_))
+ .Times(0);
+ EXPECT_CALL(*time_wait_list_manager_,
+ AddConnectionIdToTimeWait(conn_id_1, _, true, _));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id_1, _, _));
+ }
+
+ // Send a CHLO that the StatelessRejector will reject.
+ ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
+
+ // Send an identical CHLO which should get buffered.
+ check.Call(1);
+ ProcessPacket(client_addr_, conn_id_1, true, false, SerializeCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+ EXPECT_TRUE(store->HasBufferedPackets(conn_id_1));
+
+ // Complete the ProofSource::GetProof call and verify that the CHLO is
+ // rejected and the copy is discarded.
+ check.Call(2);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id_1));
+}
+
+// Test dispatcher behavior when packets time out of the buffer while CHLO
+// validation is still pending.
+TEST_F(AsyncGetProofTest, BufferTimeout) {
+ CreateTimeWaitListManager();
+
+ QuicConnectionId conn_id = 1;
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+ QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*time_wait_list_manager_,
+ ProcessPacket(_, client_addr_, conn_id, _, _));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_))
+ .Times(0);
+ }
+
+ // Send a CHLO that the StatelessRejector will accept.
+ ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+
+ // Send a data packet that will get buffered
+ check.Call(1);
+ ProcessPacket(client_addr_, conn_id, true, false, "My name is Data");
+ EXPECT_TRUE(store->HasBufferedPackets(conn_id));
+
+ // Pretend that enough time has gone by for the packets to get expired out of
+ // the buffer
+ mock_helper_.AdvanceTime(
+ QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
+ QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
+ store->OnExpirationTimeout();
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+ EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+
+ // Now allow the CHLO validation to complete, and verify that no connection
+ // gets created.
+ check.Call(2);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+ EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+}
+
+// Test behavior when packets time out of the buffer *and* the connection times
+// out of the time wait manager while CHLO validation is still pending. This
+// *should* be impossible, but anything can happen with timing conditions.
+TEST_F(AsyncGetProofTest, TimeWaitTimeout) {
+ QuicConnectionId conn_id = 1;
+ QuicBufferedPacketStore* store =
+ QuicDispatcherPeer::GetBufferedPackets(dispatcher_.get());
+ QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
+ CreateTimeWaitListManager();
+ QuicTimeWaitListManagerPeer::set_clock(time_wait_list_manager_,
+ mock_helper_.GetClock());
+
+ testing::MockFunction<void(int check_point)> check;
+ {
+ InSequence s;
+ EXPECT_CALL(check, Call(1));
+ EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
+
+ EXPECT_CALL(check, Call(2));
+ EXPECT_CALL(*dispatcher_, ShouldCreateOrBufferPacketForConnection(conn_id));
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, client_addr_))
+ .WillOnce(testing::Return(GetSession(conn_id)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(
+ GetSession(conn_id)->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(testing::WithArg<2>(
+ Invoke(CreateFunctor(&QuicDispatcherTest::ValidatePacket,
+ base::Unretained(this), conn_id))));
+ }
+
+ // Send a CHLO that the StatelessRejector will accept.
+ ProcessPacket(client_addr_, conn_id, true, false, SerializeFullCHLO());
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+
+ // Send a data packet that will get buffered
+ check.Call(1);
+ ProcessPacket(client_addr_, conn_id, true, false, "My name is Data");
+ EXPECT_TRUE(store->HasBufferedPackets(conn_id));
+
+ // Pretend that enough time has gone by for the packets to get expired out of
+ // the buffer
+ mock_helper_.AdvanceTime(
+ QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs));
+ QuicBufferedPacketStorePeer::expiration_alarm(store)->Cancel();
+ store->OnExpirationTimeout();
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+ EXPECT_TRUE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+
+ // Pretend that enough time has gone by for the connection ID to be removed
+ // from the time wait manager
+ mock_helper_.AdvanceTime(
+ QuicTimeWaitListManagerPeer::time_wait_period(time_wait_list_manager_));
+ QuicTimeWaitListManagerPeer::expiration_alarm(time_wait_list_manager_)
+ ->Cancel();
+ time_wait_list_manager_->CleanUpOldConnectionIds();
+ EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+
+ // Now allow the CHLO validation to complete. Expect that a connection is
+ // indeed created, since QUIC has forgotten that this connection ever existed.
+ // This is a miniscule corner case which should never happen in the wild, so
+ // really we are just verifying that the dispatcher does not explode in this
+ // situation.
+ check.Call(2);
+ GetFakeProofSource()->InvokePendingCallback(0);
+ ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
+ EXPECT_FALSE(store->HasBufferedPackets(conn_id));
+ EXPECT_FALSE(time_wait_list_manager_->IsConnectionIdInTimeWait(conn_id));
+}
+
} // namespace
} // namespace test
} // namespace net
« no previous file with comments | « net/tools/quic/quic_dispatcher.cc ('k') | net/tools/quic/quic_simple_server_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698