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"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/crypto_server_config.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/crypto/quic_random.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_crypto_stream.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/flip_server/epoll_server.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_time_wait_list_manager.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/test_tools/quic_test_utils.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StringPiece;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::EpollServer;
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::test::MockSession;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::tools::test::MockConnection;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::_;
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::DoAll;
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::Invoke;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::InSequence;
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::Return;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using testing::WithoutArgs;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicDispatcherPeer {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static void SetTimeWaitListManager(
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      QuicDispatcher* dispatcher,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      QuicTimeWaitListManager* time_wait_list_manager) {
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher->time_wait_list_manager_.reset(time_wait_list_manager);
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static void SetWriteBlocked(QuicDispatcher* dispatcher) {
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher->write_blocked_ = true;
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestDispatcher : public QuicDispatcher {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit TestDispatcher(const QuicConfig& config,
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const QuicCryptoServerConfig& crypto_config,
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          EpollServer* eps)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : QuicDispatcher(config, crypto_config, 1, eps) {}
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD4(CreateQuicSession, QuicSession*(
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      QuicGuid guid,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const IPEndPoint& client_address,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int fd,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      EpollServer* eps));
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  using QuicDispatcher::write_blocked_list;
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// A Connection class which unregisters the session from the dispatcher
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when sending connection close.
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// It'd be slightly more realistic to do this from the Session but it would
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// involve a lot more mocking.
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class MockServerConnection : public MockConnection {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockServerConnection(QuicGuid guid,
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       IPEndPoint address,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       int fd,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       EpollServer* eps,
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       QuicDispatcher* dispatcher)
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : MockConnection(guid, address, fd, eps, true),
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dispatcher_(dispatcher) {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void UnregisterOnConnectionClose() {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unregistering " << guid();
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher_->OnConnectionClose(guid(), QUIC_NO_ERROR);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcher* dispatcher_;
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSession* CreateSession(QuicDispatcher* dispatcher,
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           QuicGuid guid,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           const IPEndPoint& addr,
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           MockSession** session,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           EpollServer* eps) {
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockServerConnection* connection =
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockServerConnection(guid, addr, 0, eps, dispatcher);
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *session = new MockSession(connection, true);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      WithoutArgs(Invoke(
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          connection, &MockServerConnection::UnregisterOnConnectionClose)));
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              ProcessUdpPacket(_, addr, _));
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return *session;
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class QuicDispatcherTest : public ::testing::Test {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcherTest()
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : crypto_config_(QuicCryptoServerConfig::TESTING,
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       QuicRandom::GetInstance()),
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dispatcher_(config_, crypto_config_, &eps_),
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session1_(NULL),
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        session2_(NULL) {
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~QuicDispatcherTest() {}
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnection* connection1() {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return reinterpret_cast<MockConnection*>(session1_->connection());
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockConnection* connection2() {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return reinterpret_cast<MockConnection*>(session2_->connection());
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ProcessPacket(IPEndPoint addr,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     QuicGuid guid,
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     const string& data) {
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicEncryptedPacket packet(data.data(), data.length());
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ValidatePacket(const QuicEncryptedPacket& packet) {
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPAddressNumber Loopback4() {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    net::IPAddressNumber addr;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return addr;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EpollServer eps_;
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicConfig config_;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicCryptoServerConfig crypto_config_;
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestDispatcher dispatcher_;
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockSession* session1_;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockSession* session2_;
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  string data_;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, ProcessPackets) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint addr(Loopback4(), 1);
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr, _, &eps_))
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &dispatcher_, 1, addr, &session1_, &eps_)));
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, 1, "foo");
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr, _, &eps_))
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    &dispatcher_, 2, addr, &session2_, &eps_)));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, 2, "bar");
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data_ = "eep";
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)));
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, 1, "eep");
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, Shutdown) {
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint addr(Loopback4(), 1);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    &dispatcher_, 1, addr, &session1_, &eps_)));
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, 1, "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,
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          EpollServer* eps)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : QuicTimeWaitListManager(writer, eps) {
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   const IPEndPoint& client_address,
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   QuicGuid guid,
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   const QuicEncryptedPacket& packet));
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(QuicDispatcherTest, TimeWaitListManager) {
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockTimeWaitListManager* time_wait_list_manager =
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new MockTimeWaitListManager(&dispatcher_, &eps_);
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // dispatcher takes the ownership of time_wait_list_manager.
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             time_wait_list_manager);
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Create a new session.
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint addr(Loopback4(), 1);
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicGuid guid = 1;
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr, _, &eps_))
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(testing::Return(CreateSession(
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    &dispatcher_, guid, addr, &session1_, &eps_)));
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, guid, "foo");
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Close the connection by sending public reset packet.
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicPublicResetPacket packet;
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.guid = guid;
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.reset_flag = true;
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.public_header.version_flag = false;
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.rejected_sequence_number = 19191;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  packet.nonce_proof = 132232;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<QuicEncryptedPacket> encrypted(
2212385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      QuicFramer::BuildPublicResetPacket(packet));
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*session1_, ConnectionClose(QUIC_PUBLIC_RESET, true)).Times(1)
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(WithoutArgs(Invoke(
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          reinterpret_cast<MockServerConnection*>(session1_->connection()),
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &MockServerConnection::UnregisterOnConnectionClose)));
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              ProcessUdpPacket(_, _, _))
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .WillOnce(Invoke(
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          reinterpret_cast<MockConnection*>(session1_->connection()),
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          &MockConnection::ReallyProcessUdpPacket));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted);
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Dispatcher forwards subsequent packets for this guid to the time wait list
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // manager.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ProcessPacket(addr, guid, "foo");
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class WriteBlockedListTest : public QuicDispatcherTest {
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPEndPoint addr(Loopback4(), 1);
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(testing::Return(CreateSession(
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      &dispatcher_, 1, addr, &session1_, &eps_)));
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProcessPacket(addr, 1, "foo");
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        .WillOnce(testing::Return(CreateSession(
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      &dispatcher_, 2, addr, &session2_, &eps_)));
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ProcessPacket(addr, 2, "bar");
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    blocked_list_ = dispatcher_.write_blocked_list();
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown() {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(*connection1(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(*connection2(), SendConnectionClose(QUIC_PEER_GOING_AWAY));
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dispatcher_.Shutdown();
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool SetBlocked() {
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    QuicDispatcherPeer::SetWriteBlocked(&dispatcher_);
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return true;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicDispatcher::WriteBlockedList* blocked_list_;
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, BasicOnCanWrite) {
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // No OnCanWrite calls because no connections are blocked.
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Register connection 1 for events, and make sure it's nofitied.
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // It should get only one notification.
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(dispatcher_.OnCanWrite());
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, OnCanWriteOrder) {
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure we handle events in order.
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check the other ordering.
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, OnCanWriteRemove) {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add and remove one connction.
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->RemoveBlockedObject(connection1());
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add and remove one connction and make sure it doesn't affect others.
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->RemoveBlockedObject(connection1());
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add it, remove it, and add it back and make sure things are OK.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->RemoveBlockedObject(connection1());
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, DoubleAdd) {
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure a double add does not necessitate a double remove.
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->RemoveBlockedObject(connection1());
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(0);
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure a double add does not result in two OnCanWrite calls.
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).Times(1);
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, OnCanWriteHandleBlock) {
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally make sure if we write block on a write call, we stop calling.
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Invoke(this, &WriteBlockedListTest::SetBlocked));
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // And we'll resume where we left off when we get another call.
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, LimitedWrites) {
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure we call both writers.  The first will register for more writing
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // but should not be immediately called due to limits.
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(Return(true));
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).WillOnce(Return(false));
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Now call OnCanWrite again, and connection1 should get its second chance
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite());
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(WriteBlockedListTest, TestWriteLimits) {
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally make sure if we write block on a write call, we stop calling.
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  InSequence s;
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection1());
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocked_list_->AddBlockedObject(connection2());
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection1(), OnCanWrite()).WillOnce(
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Invoke(this, &WriteBlockedListTest::SetBlocked));
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite()).Times(0);
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // And we'll resume where we left off when we get another call.
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(*connection2(), OnCanWrite());
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dispatcher_.OnCanWrite();
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace test
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
391