1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_dispatcher.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/crypto_handshake.h"
110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/quic/crypto/quic_crypto_server_config.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/crypto/quic_random.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_crypto_stream.h"
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "net/quic/quic_flags.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/quic/quic_utils.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/epoll_server/epoll_server.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/tools/quic/quic_packet_writer_wrapper.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_time_wait_list_manager.h"
201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/test_tools/quic_test_utils.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StringPiece;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::EpollServer;
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using net::test::ConstructEncryptedPacket;
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using net::test::MockSession;
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using net::test::ValueRestore;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::tools::test::MockConnection;
313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)using std::make_pair;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::DoAll;
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::InSequence;
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using testing::Invoke;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::WithoutArgs;
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)using testing::_;
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestDispatcher : public QuicDispatcher {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit TestDispatcher(const QuicConfig& config,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const QuicCryptoServerConfig& crypto_config,
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          EpollServer* eps)
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      : QuicDispatcher(config,
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       crypto_config,
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       QuicSupportedVersions(),
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                       new QuicDispatcher::DefaultPacketWriterFactory(),
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       eps) {
531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MOCK_METHOD3(CreateQuicSession, QuicSession*(
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      QuicConnectionId connection_id,
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const IPEndPoint& server_address,
581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      const IPEndPoint& client_address));
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  using QuicDispatcher::current_server_address;
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  using QuicDispatcher::current_client_address;
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A Connection class which unregisters the session from the dispatcher
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when sending connection close.
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// It'd be slightly more realistic to do this from the Session but it would
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// involve a lot more mocking.
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockServerConnection : public MockConnection {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockServerConnection(QuicConnectionId connection_id,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       QuicDispatcher* dispatcher)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : MockConnection(connection_id, true),
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        dispatcher_(dispatcher) {}
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  void UnregisterOnConnectionClosed() {
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Unregistering " << connection_id();
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    dispatcher_->OnConnectionClosed(connection_id(), QUIC_NO_ERROR);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcher* dispatcher_;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSession* CreateSession(QuicDispatcher* dispatcher,
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                           QuicConnectionId connection_id,
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           const IPEndPoint& client_address,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           MockSession** session) {
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockServerConnection* connection =
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      new MockServerConnection(connection_id, dispatcher);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *session = new MockSession(connection);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WithoutArgs(Invoke(
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          connection, &MockServerConnection::UnregisterOnConnectionClosed)));
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch              ProcessUdpPacket(_, client_address, _));
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return *session;
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicDispatcherTest : public ::testing::Test {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcherTest()
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : crypto_config_(QuicCryptoServerConfig::TESTING,
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       QuicRandom::GetInstance()),
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dispatcher_(config_, crypto_config_, &eps_),
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session1_(NULL),
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session2_(NULL) {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dispatcher_.Initialize(1);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~QuicDispatcherTest() {}
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnection* connection1() {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return reinterpret_cast<MockConnection*>(session1_->connection());
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnection* connection2() {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return reinterpret_cast<MockConnection*>(session2_->connection());
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void ProcessPacket(IPEndPoint client_address,
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                     QuicConnectionId connection_id,
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     bool has_version_flag,
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     const string& data) {
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        connection_id, has_version_flag, false, 1, data));
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    data_ = string(packet->data(), packet->length());
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatcher_.ProcessPacket(server_address_, client_address, *packet);
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ValidatePacket(const QuicEncryptedPacket& packet) {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(data_.length(), packet.AsStringPiece().length());
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_EQ(data_, packet.AsStringPiece());
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EpollServer eps_;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicConfig config_;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicCryptoServerConfig crypto_config_;
138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPEndPoint server_address_;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestDispatcher dispatcher_;
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockSession* session1_;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockSession* session2_;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string data_;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, ProcessPackets) {
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPEndPoint client_address(net::test::Loopback4(), 1);
147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPAddressNumber any4;
148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  server_address_ = IPEndPoint(any4, 5);
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, client_address))
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          &dispatcher_, 1, client_address, &session1_)));
154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, 1, true, "foo");
155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_EQ(client_address, dispatcher_.current_client_address());
156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_EQ(server_address_, dispatcher_.current_server_address());
157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, client_address))
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    &dispatcher_, 2, client_address, &session2_)));
162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, 2, true, "bar");
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              ProcessUdpPacket(_, _, _)).Times(1).
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WillOnce(testing::WithArgs<2>(Invoke(
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this, &QuicDispatcherTest::ValidatePacket)));
168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, 1, false, "eep");
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, Shutdown) {
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPEndPoint client_address(net::test::Loopback4(), 1);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    &dispatcher_, 1, client_address, &session1_)));
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, 1, true, "foo");
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              SendConnectionClose(QUIC_PEER_GOING_AWAY));
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.Shutdown();
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockTimeWaitListManager : public QuicTimeWaitListManager {
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockTimeWaitListManager(QuicPacketWriter* writer,
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          QuicServerSessionVisitor* visitor,
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          EpollServer* eps)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : QuicTimeWaitListManager(writer, visitor, eps, QuicSupportedVersions()) {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MOCK_METHOD5(ProcessPacket, void(const IPEndPoint& server_address,
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   const IPEndPoint& client_address,
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   QuicConnectionId connection_id,
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                   QuicPacketSequenceNumber sequence_number,
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                   const QuicEncryptedPacket& packet));
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, TimeWaitListManager) {
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockTimeWaitListManager* time_wait_list_manager =
2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new MockTimeWaitListManager(
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // dispatcher takes the ownership of time_wait_list_manager.
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             time_wait_list_manager);
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create a new session.
209e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPEndPoint client_address(net::test::Loopback4(), 1);
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  QuicConnectionId connection_id = 1;
211e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  EXPECT_CALL(dispatcher_, CreateQuicSession(connection_id, _, client_address))
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
213e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                    &dispatcher_, connection_id, client_address, &session1_)));
214e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, connection_id, true, "foo");
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Close the connection by sending public reset packet.
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicPublicResetPacket packet;
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  packet.public_header.connection_id = connection_id;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.reset_flag = true;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.version_flag = false;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.rejected_sequence_number = 19191;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.nonce_proof = 132232;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> encrypted(
2242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      QuicFramer::BuildPublicResetPacket(packet));
2251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(WithoutArgs(Invoke(
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          reinterpret_cast<MockServerConnection*>(session1_->connection()),
2281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          &MockServerConnection::UnregisterOnConnectionClosed)));
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              ProcessUdpPacket(_, _, _))
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(Invoke(
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          reinterpret_cast<MockConnection*>(session1_->connection()),
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &MockConnection::ReallyProcessUdpPacket));
234e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  dispatcher_.ProcessPacket(IPEndPoint(), client_address, *encrypted);
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(time_wait_list_manager->IsConnectionIdInTimeWait(connection_id));
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dispatcher forwards subsequent packets for this connection_id to the time
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // wait list manager.
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*time_wait_list_manager,
2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              ProcessPacket(_, _, connection_id, _, _)).Times(1);
241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, connection_id, true, "foo");
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockTimeWaitListManager* time_wait_list_manager =
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      new MockTimeWaitListManager(
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          QuicDispatcherPeer::GetWriter(&dispatcher_), &dispatcher_, &eps_);
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // dispatcher takes the ownership of time_wait_list_manager.
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                             time_wait_list_manager);
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
252e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  IPEndPoint client_address(net::test::Loopback4(), 1);
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  QuicConnectionId connection_id = 1;
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Dispatcher forwards all packets for this connection_id to the time wait
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // list manager.
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*time_wait_list_manager,
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              ProcessPacket(_, _, connection_id, _, _)).Times(1);
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  string data = "foo";
260e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessPacket(client_address, connection_id, false, "foo");
261e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
262e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BlockingWriter : public QuicPacketWriterWrapper {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BlockingWriter() : write_blocked_(false) {}
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool IsWriteBlocked() const OVERRIDE { return write_blocked_; }
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void SetWritable() OVERRIDE { write_blocked_ = false; }
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual WriteResult WritePacket(
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const char* buffer,
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t buf_len,
273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const IPAddressNumber& self_client_address,
274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      const IPEndPoint& peer_client_address) OVERRIDE {
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // It would be quite possible to actually implement this method here with
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // the fake blocked status, but it would be significantly more work in
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // Chromium, and since it's not called anyway, don't bother.
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    LOG(DFATAL) << "Not supported";
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return WriteResult();
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool write_blocked_;
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class QuicDispatcherWriteBlockedListTest : public QuicDispatcherTest {
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() {
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    writer_ = new BlockingWriter;
28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    QuicDispatcherPeer::SetPacketWriterFactory(&dispatcher_,
29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                               new TestWriterFactory());
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicDispatcherPeer::UseWriter(&dispatcher_, writer_);
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    IPEndPoint client_address(net::test::Loopback4(), 1);
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
295e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(testing::Return(CreateSession(
297e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      &dispatcher_, 1, client_address, &session1_)));
298e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ProcessPacket(client_address, 1, true, "foo");
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
300e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, client_address))
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(testing::Return(CreateSession(
302e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                      &dispatcher_, 2, client_address, &session2_)));
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ProcessPacket(client_address, 2, true, "bar");
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blocked_list_ = QuicDispatcherPeer::GetWriteBlockedList(&dispatcher_);
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown() {
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher_.Shutdown();
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
314a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetBlocked() {
315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    writer_->write_blocked_ = true;
316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void BlockConnection2() {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    writer_->write_blocked_ = true;
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    dispatcher_.OnWriteBlocked(connection2());
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BlockingWriter* writer_;
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcher::WriteBlockedList* blocked_list_;
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, BasicOnCanWrite) {
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // No OnCanWrite calls because no connections are blocked.
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Register connection 1 for events, and make sure it's notified.
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It should get only one notification.
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  dispatcher_.OnCanWrite();
341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(dispatcher_.HasPendingWrites());
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteOrder) {
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure we handle events in order.
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check the other ordering.
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteRemove) {
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add and remove one connction.
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  blocked_list_->erase(connection1());
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add and remove one connction and make sure it doesn't affect others.
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  blocked_list_->erase(connection1());
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add it, remove it, and add it back and make sure things are OK.
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  blocked_list_->erase(connection1());
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, DoubleAdd) {
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure a double add does not necessitate a double remove.
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
3933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  blocked_list_->erase(connection1());
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure a double add does not result in two OnCanWrite calls.
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, OnCanWriteHandleBlock) {
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally make sure if we write block on a write call, we stop calling.
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // And we'll resume where we left off when we get another call.
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, LimitedWrites) {
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure we call both writers.  The first will register for more writing
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // but should not be immediately called due to limits.
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(
430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Invoke(this, &QuicDispatcherWriteBlockedListTest::BlockConnection2));
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(dispatcher_.HasPendingWrites());
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Now call OnCanWrite again, and connection1 should get its second chance
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(dispatcher_.HasPendingWrites());
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(QuicDispatcherWriteBlockedListTest, TestWriteLimits) {
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally make sure if we write block on a write call, we stop calling.
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBlocked();
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection1());
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dispatcher_.OnWriteBlocked(connection2());
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Invoke(this, &QuicDispatcherWriteBlockedListTest::SetBlocked));
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(dispatcher_.HasPendingWrites());
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // And we'll resume where we left off when we get another call.
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(dispatcher_.HasPendingWrites());
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace test
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
462