Home | History | Annotate | Download | only in quic
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <stddef.h>
      6 #include <string>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/memory/singleton.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/synchronization/waitable_event.h"
     12 #include "base/threading/simple_thread.h"
     13 #include "net/base/ip_endpoint.h"
     14 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
     15 #include "net/quic/crypto/null_encrypter.h"
     16 #include "net/quic/quic_framer.h"
     17 #include "net/quic/quic_packet_creator.h"
     18 #include "net/quic/quic_protocol.h"
     19 #include "net/quic/test_tools/quic_connection_peer.h"
     20 #include "net/quic/test_tools/quic_session_peer.h"
     21 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
     22 #include "net/tools/quic/quic_epoll_connection_helper.h"
     23 #include "net/tools/quic/quic_in_memory_cache.h"
     24 #include "net/tools/quic/quic_server.h"
     25 #include "net/tools/quic/quic_socket_utils.h"
     26 #include "net/tools/quic/test_tools/http_message_test_utils.h"
     27 #include "net/tools/quic/test_tools/quic_client_peer.h"
     28 #include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h"
     29 #include "net/tools/quic/test_tools/quic_test_client.h"
     30 #include "testing/gtest/include/gtest/gtest.h"
     31 
     32 using base::StringPiece;
     33 using base::WaitableEvent;
     34 using net::test::QuicConnectionPeer;
     35 using net::test::QuicSessionPeer;
     36 using net::test::ReliableQuicStreamPeer;
     37 using std::string;
     38 
     39 namespace net {
     40 namespace tools {
     41 namespace test {
     42 namespace {
     43 
     44 const char* kFooResponseBody = "Artichoke hearts make me happy.";
     45 const char* kBarResponseBody = "Palm hearts are pretty delicious, also.";
     46 const size_t kCongestionFeedbackFrameSize = 25;
     47 // If kCongestionFeedbackFrameSize increase we need to expand this string
     48 // accordingly.
     49 const char* kLargeRequest =
     50     "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes";
     51 
     52 void GenerateBody(string* body, int length) {
     53   body->clear();
     54   body->reserve(length);
     55   for (int i = 0; i < length; ++i) {
     56     body->append(1, static_cast<char>(32 + i % (126 - 32)));
     57   }
     58 }
     59 
     60 
     61 // Simple wrapper class to run server in a thread.
     62 class ServerThread : public base::SimpleThread {
     63  public:
     64   explicit ServerThread(IPEndPoint address, const QuicConfig& config)
     65       : SimpleThread("server_thread"),
     66         listening_(true, false),
     67         quit_(true, false),
     68         server_(config),
     69         address_(address),
     70         port_(0) {
     71   }
     72   virtual ~ServerThread() {
     73   }
     74 
     75   virtual void Run() OVERRIDE {
     76     server_.Listen(address_);
     77 
     78     port_lock_.Acquire();
     79     port_ = server_.port();
     80     port_lock_.Release();
     81 
     82     listening_.Signal();
     83     while (!quit_.IsSignaled()) {
     84       server_.WaitForEvents();
     85     }
     86     server_.Shutdown();
     87   }
     88 
     89   int GetPort() {
     90     port_lock_.Acquire();
     91     int rc = port_;
     92     port_lock_.Release();
     93     return rc;
     94   }
     95 
     96   WaitableEvent* listening() { return &listening_; }
     97   WaitableEvent* quit() { return &quit_; }
     98 
     99  private:
    100   WaitableEvent listening_;
    101   WaitableEvent quit_;
    102   base::Lock port_lock_;
    103   QuicServer server_;
    104   IPEndPoint address_;
    105   int port_;
    106 
    107   DISALLOW_COPY_AND_ASSIGN(ServerThread);
    108 };
    109 
    110 class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
    111  public:
    112   static void SetUpTestCase() {
    113     QuicInMemoryCache::GetInstance()->ResetForTests();
    114   }
    115 
    116  protected:
    117   EndToEndTest()
    118       : server_hostname_("example.com"),
    119         server_started_(false) {
    120     net::IPAddressNumber ip;
    121     CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
    122     server_address_ = IPEndPoint(ip, 0);
    123     client_config_.SetDefaults();
    124     server_config_.SetDefaults();
    125 
    126     AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody);
    127     AddToCache("GET", "https://www.google.com/foo",
    128                "HTTP/1.1", "200", "OK", kFooResponseBody);
    129     AddToCache("GET", "https://www.google.com/bar",
    130                "HTTP/1.1", "200", "OK", kBarResponseBody);
    131     version_ = GetParam();
    132   }
    133 
    134   virtual QuicTestClient* CreateQuicClient() {
    135     QuicTestClient* client = new QuicTestClient(server_address_,
    136                                                 server_hostname_,
    137                                                 false,  // not secure
    138                                                 client_config_,
    139                                                 version_);
    140     client->Connect();
    141     return client;
    142   }
    143 
    144   virtual bool Initialize() {
    145     // Start the server first, because CreateQuicClient() attempts
    146     // to connect to the server.
    147     StartServer();
    148     client_.reset(CreateQuicClient());
    149     return client_->client()->connected();
    150   }
    151 
    152   virtual void TearDown() {
    153     StopServer();
    154   }
    155 
    156   void StartServer() {
    157     server_thread_.reset(new ServerThread(server_address_, server_config_));
    158     server_thread_->Start();
    159     server_thread_->listening()->Wait();
    160     server_address_ = IPEndPoint(server_address_.address(),
    161                                  server_thread_->GetPort());
    162     server_started_ = true;
    163   }
    164 
    165   void StopServer() {
    166     if (!server_started_)
    167       return;
    168     if (server_thread_.get()) {
    169       server_thread_->quit()->Signal();
    170       server_thread_->Join();
    171     }
    172   }
    173 
    174   void AddToCache(const StringPiece& method,
    175                   const StringPiece& path,
    176                   const StringPiece& version,
    177                   const StringPiece& response_code,
    178                   const StringPiece& response_detail,
    179                   const StringPiece& body) {
    180     BalsaHeaders request_headers, response_headers;
    181     request_headers.SetRequestFirstlineFromStringPieces(method,
    182                                                         path,
    183                                                         version);
    184     response_headers.SetRequestFirstlineFromStringPieces(version,
    185                                                          response_code,
    186                                                          response_detail);
    187     response_headers.AppendHeader("content-length",
    188                                   base::IntToString(body.length()));
    189 
    190     // Check if response already exists and matches.
    191     QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
    192     const QuicInMemoryCache::Response* cached_response =
    193         cache->GetResponse(request_headers);
    194     if (cached_response != NULL) {
    195       string cached_response_headers_str, response_headers_str;
    196       cached_response->headers().DumpToString(&cached_response_headers_str);
    197       response_headers.DumpToString(&response_headers_str);
    198       CHECK_EQ(cached_response_headers_str, response_headers_str);
    199       CHECK_EQ(cached_response->body(), body);
    200       return;
    201     }
    202     cache->AddResponse(request_headers, response_headers, body);
    203   }
    204 
    205   IPEndPoint server_address_;
    206   string server_hostname_;
    207   scoped_ptr<ServerThread> server_thread_;
    208   scoped_ptr<QuicTestClient> client_;
    209   bool server_started_;
    210   QuicConfig client_config_;
    211   QuicConfig server_config_;
    212   QuicVersion version_;
    213 };
    214 
    215 // Run all end to end tests with all supported versions.
    216 INSTANTIATE_TEST_CASE_P(EndToEndTests,
    217                         EndToEndTest,
    218                         ::testing::ValuesIn(kSupportedQuicVersions));
    219 
    220 TEST_P(EndToEndTest, SimpleRequestResponse) {
    221   // TODO(rtenneti): Delete this when NSS is supported.
    222   if (!Aes128Gcm12Encrypter::IsSupported()) {
    223     LOG(INFO) << "AES GCM not supported. Test skipped.";
    224     return;
    225   }
    226 
    227   ASSERT_TRUE(Initialize());
    228 
    229   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
    230   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    231 }
    232 
    233 // TODO(rch): figure out how to detect missing v6 supprt (like on the linux
    234 // try bots) and selectively disable this test.
    235 TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
    236   // TODO(rtenneti): Delete this when NSS is supported.
    237   if (!Aes128Gcm12Encrypter::IsSupported()) {
    238     LOG(INFO) << "AES GCM not supported. Test skipped.";
    239     return;
    240   }
    241 
    242   IPAddressNumber ip;
    243   CHECK(net::ParseIPLiteralToNumber("::1", &ip));
    244   server_address_ = IPEndPoint(ip, server_address_.port());
    245   ASSERT_TRUE(Initialize());
    246 
    247   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
    248   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    249 }
    250 
    251 TEST_P(EndToEndTest, SeparateFinPacket) {
    252   // TODO(rtenneti): Delete this when NSS is supported.
    253   if (!Aes128Gcm12Encrypter::IsSupported()) {
    254     LOG(INFO) << "AES GCM not supported. Test skipped.";
    255     return;
    256   }
    257 
    258   ASSERT_TRUE(Initialize());
    259 
    260   HTTPMessage request(HttpConstants::HTTP_1_1,
    261                       HttpConstants::POST, "/foo");
    262   request.set_has_complete_message(false);
    263 
    264   client_->SendMessage(request);
    265 
    266   client_->SendData(string(), true);
    267 
    268   client_->WaitForResponse();
    269   EXPECT_EQ(kFooResponseBody, client_->response_body());
    270   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    271 
    272   request.AddBody("foo", true);
    273 
    274   client_->SendMessage(request);
    275   client_->SendData(string(), true);
    276   client_->WaitForResponse();
    277   EXPECT_EQ(kFooResponseBody, client_->response_body());
    278   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    279 }
    280 
    281 TEST_P(EndToEndTest, MultipleRequestResponse) {
    282   // TODO(rtenneti): Delete this when NSS is supported.
    283   if (!Aes128Gcm12Encrypter::IsSupported()) {
    284     LOG(INFO) << "AES GCM not supported. Test skipped.";
    285     return;
    286   }
    287 
    288   ASSERT_TRUE(Initialize());
    289 
    290   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
    291   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    292   EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
    293   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    294 }
    295 
    296 TEST_P(EndToEndTest, MultipleClients) {
    297   // TODO(rtenneti): Delete this when NSS is supported.
    298   if (!Aes128Gcm12Encrypter::IsSupported()) {
    299     LOG(INFO) << "AES GCM not supported. Test skipped.";
    300     return;
    301   }
    302 
    303   ASSERT_TRUE(Initialize());
    304   scoped_ptr<QuicTestClient> client2(CreateQuicClient());
    305 
    306   HTTPMessage request(HttpConstants::HTTP_1_1,
    307                       HttpConstants::POST, "/foo");
    308   request.AddHeader("content-length", "3");
    309   request.set_has_complete_message(false);
    310 
    311   client_->SendMessage(request);
    312   client2->SendMessage(request);
    313 
    314   client_->SendData("bar", true);
    315   client_->WaitForResponse();
    316   EXPECT_EQ(kFooResponseBody, client_->response_body());
    317   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    318 
    319   client2->SendData("eep", true);
    320   client2->WaitForResponse();
    321   EXPECT_EQ(kFooResponseBody, client2->response_body());
    322   EXPECT_EQ(200u, client2->response_headers()->parsed_response_code());
    323 }
    324 
    325 TEST_P(EndToEndTest, RequestOverMultiplePackets) {
    326   // TODO(rtenneti): Delete this when NSS is supported.
    327   if (!Aes128Gcm12Encrypter::IsSupported()) {
    328     LOG(INFO) << "AES GCM not supported. Test skipped.";
    329     return;
    330   }
    331 
    332   ASSERT_TRUE(Initialize());
    333   // Set things up so we have a small payload, to guarantee fragmentation.
    334   // A congestion feedback frame can't be split into multiple packets, make sure
    335   // that our packet have room for at least this amount after the normal headers
    336   // are added.
    337 
    338   // TODO(rch) handle this better when we have different encryption options.
    339   const size_t kStreamDataLength = 3;
    340   const QuicStreamId kStreamId = 1u;
    341   const QuicStreamOffset kStreamOffset = 0u;
    342   size_t stream_payload_size =
    343       QuicFramer::GetMinStreamFrameSize(
    344           GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
    345   size_t min_payload_size =
    346       std::max(kCongestionFeedbackFrameSize, stream_payload_size);
    347   size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
    348   // TODO(satyashekhar): Fix this when versioning is implemented.
    349   client_->options()->max_packet_length =
    350       GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
    351                           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
    352       ciphertext_size;
    353 
    354   // Make sure our request is too large to fit in one packet.
    355   EXPECT_GT(strlen(kLargeRequest), min_payload_size);
    356   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
    357   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    358 }
    359 
    360 TEST_P(EndToEndTest, MultipleFramesRandomOrder) {
    361   // TODO(rtenneti): Delete this when NSS is supported.
    362   if (!Aes128Gcm12Encrypter::IsSupported()) {
    363     LOG(INFO) << "AES GCM not supported. Test skipped.";
    364     return;
    365   }
    366 
    367   ASSERT_TRUE(Initialize());
    368   // Set things up so we have a small payload, to guarantee fragmentation.
    369   // A congestion feedback frame can't be split into multiple packets, make sure
    370   // that our packet have room for at least this amount after the normal headers
    371   // are added.
    372 
    373   // TODO(rch) handle this better when we have different encryption options.
    374   const size_t kStreamDataLength = 3;
    375   const QuicStreamId kStreamId = 1u;
    376   const QuicStreamOffset kStreamOffset = 0u;
    377   size_t stream_payload_size =
    378       QuicFramer::GetMinStreamFrameSize(
    379           GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
    380   size_t min_payload_size =
    381       std::max(kCongestionFeedbackFrameSize, stream_payload_size);
    382   size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
    383   // TODO(satyashekhar): Fix this when versioning is implemented.
    384   client_->options()->max_packet_length =
    385       GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
    386                           PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
    387       ciphertext_size;
    388   client_->options()->random_reorder = true;
    389 
    390   // Make sure our request is too large to fit in one packet.
    391   EXPECT_GT(strlen(kLargeRequest), min_payload_size);
    392   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
    393   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    394 }
    395 
    396 TEST_P(EndToEndTest, PostMissingBytes) {
    397   // TODO(rtenneti): Delete this when NSS is supported.
    398   if (!Aes128Gcm12Encrypter::IsSupported()) {
    399     LOG(INFO) << "AES GCM not supported. Test skipped.";
    400     return;
    401   }
    402 
    403   ASSERT_TRUE(Initialize());
    404 
    405   // Add a content length header with no body.
    406   HTTPMessage request(HttpConstants::HTTP_1_1,
    407                       HttpConstants::POST, "/foo");
    408   request.AddHeader("content-length", "3");
    409   request.set_skip_message_validation(true);
    410 
    411   // This should be detected as stream fin without complete request,
    412   // triggering an error response.
    413   client_->SendCustomSynchronousRequest(request);
    414   EXPECT_EQ("bad", client_->response_body());
    415   EXPECT_EQ(500u, client_->response_headers()->parsed_response_code());
    416 }
    417 
    418 TEST_P(EndToEndTest, LargePost) {
    419   // TODO(rtenneti): Delete this when NSS is supported.
    420   if (!Aes128Gcm12Encrypter::IsSupported()) {
    421     LOG(INFO) << "AES GCM not supported. Test skipped.";
    422     return;
    423   }
    424 
    425   // Connect with lower fake packet loss than we'd like to test.  Until
    426   // b/10126687 is fixed, losing handshake packets is pretty brutal.
    427   // FLAGS_fake_packet_loss_percentage = 5;
    428   ASSERT_TRUE(Initialize());
    429 
    430   // Wait for the server SHLO before upping the packet loss.
    431   client_->client()->WaitForCryptoHandshakeConfirmed();
    432   // FLAGS_fake_packet_loss_percentage = 30;
    433 
    434   string body;
    435   GenerateBody(&body, 10240);
    436 
    437   HTTPMessage request(HttpConstants::HTTP_1_1,
    438                       HttpConstants::POST, "/foo");
    439   request.AddBody(body, true);
    440 
    441   EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
    442 }
    443 
    444 // TODO(ianswett): Enable once b/9295090 is fixed.
    445 TEST_P(EndToEndTest, DISABLED_LargePostFEC) {
    446   // FLAGS_fake_packet_loss_percentage = 30;
    447   ASSERT_TRUE(Initialize());
    448   client_->options()->max_packets_per_fec_group = 6;
    449 
    450   // TODO(rtenneti): Delete this when NSS is supported.
    451   if (!Aes128Gcm12Encrypter::IsSupported()) {
    452     LOG(INFO) << "AES GCM not supported. Test skipped.";
    453     return;
    454   }
    455 
    456   // FLAGS_fake_packet_loss_percentage = 30;
    457   ASSERT_TRUE(Initialize());
    458   client_->options()->max_packets_per_fec_group = 6;
    459 
    460   string body;
    461   GenerateBody(&body, 10240);
    462 
    463   HTTPMessage request(HttpConstants::HTTP_1_1,
    464                       HttpConstants::POST, "/foo");
    465   request.AddBody(body, true);
    466 
    467   EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
    468 }
    469 
    470 /*TEST_P(EndToEndTest, PacketTooLarge) {
    471   FLAGS_quic_allow_oversized_packets_for_test = true;
    472   ASSERT_TRUE(Initialize());
    473 
    474   string body;
    475   GenerateBody(&body, kMaxPacketSize);
    476 
    477   HTTPMessage request(HttpConstants::HTTP_1_1,
    478                       HttpConstants::POST, "/foo");
    479   request.AddBody(body, true);
    480   client_->options()->max_packet_length = 20480;
    481 
    482   EXPECT_EQ("", client_->SendCustomSynchronousRequest(request));
    483   EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
    484   EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error());
    485 }*/
    486 
    487 TEST_P(EndToEndTest, InvalidStream) {
    488   // TODO(rtenneti): Delete this when NSS is supported.
    489   if (!Aes128Gcm12Encrypter::IsSupported()) {
    490     LOG(INFO) << "AES GCM not supported. Test skipped.";
    491     return;
    492   }
    493 
    494   ASSERT_TRUE(Initialize());
    495 
    496   string body;
    497   GenerateBody(&body, kMaxPacketSize);
    498 
    499   HTTPMessage request(HttpConstants::HTTP_1_1,
    500                       HttpConstants::POST, "/foo");
    501   request.AddBody(body, true);
    502   // Force the client to write with a stream ID belonging to a nonexistent
    503   // server-side stream.
    504   QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2);
    505 
    506   client_->SendCustomSynchronousRequest(request);
    507 //  EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
    508   EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM, client_->connection_error());
    509 }
    510 
    511 // TODO(rch): this test seems to cause net_unittests timeouts :|
    512 TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
    513   // TODO(rtenneti): Delete this when NSS is supported.
    514   if (!Aes128Gcm12Encrypter::IsSupported()) {
    515     LOG(INFO) << "AES GCM not supported. Test skipped.";
    516     return;
    517   }
    518 
    519   ASSERT_TRUE(Initialize());
    520   scoped_ptr<QuicTestClient> client2(CreateQuicClient());
    521 
    522   HTTPMessage request(HttpConstants::HTTP_1_1,
    523                       HttpConstants::POST, "/foo");
    524   request.AddHeader("content-length", "3");
    525   request.set_has_complete_message(false);
    526 
    527   // Set the offset so we won't frame.  Otherwise when we pick up termination
    528   // before HTTP framing is complete, we send an error and close the stream,
    529   // and the second write is picked up as writing on a closed stream.
    530   QuicReliableClientStream* stream = client_->GetOrCreateStream();
    531   ASSERT_TRUE(stream != NULL);
    532   ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream);
    533 
    534   client_->SendData("bar", true);
    535 
    536   // By default the stream protects itself from writes after terminte is set.
    537   // Override this to test the server handling buggy clients.
    538   ReliableQuicStreamPeer::SetWriteSideClosed(
    539       false, client_->GetOrCreateStream());
    540 
    541 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
    542 #if !defined(DCHECK_ALWAYS_ON)
    543   EXPECT_DEBUG_DEATH({
    544       client_->SendData("eep", true);
    545       client_->WaitForResponse();
    546       EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
    547     },
    548     "Check failed: !fin_buffered_");
    549 #else
    550   EXPECT_DEATH({
    551       client_->SendData("eep", true);
    552       client_->WaitForResponse();
    553       EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
    554     },
    555     "Check failed: !fin_buffered_");
    556 #endif
    557 #endif
    558 }
    559 
    560 TEST_P(EndToEndTest, Timeout) {
    561   client_config_.set_idle_connection_state_lifetime(
    562       QuicTime::Delta::FromMicroseconds(500),
    563       QuicTime::Delta::FromMicroseconds(500));
    564   // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake:
    565   // that's enough to validate timeout in this case.
    566   Initialize();
    567   while (client_->client()->connected()) {
    568     client_->client()->WaitForEvents();
    569   }
    570 }
    571 
    572 TEST_P(EndToEndTest, LimitMaxOpenStreams) {
    573   // Server limits the number of max streams to 2.
    574   server_config_.set_max_streams_per_connection(2, 2);
    575   // Client tries to negotiate for 10.
    576   client_config_.set_max_streams_per_connection(10, 5);
    577 
    578   ASSERT_TRUE(Initialize());
    579   client_->client()->WaitForCryptoHandshakeConfirmed();
    580   QuicConfig* client_negotiated_config = client_->client()->session()->config();
    581   EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection());
    582 }
    583 
    584 TEST_P(EndToEndTest, ResetConnection) {
    585   // TODO(rtenneti): Delete this when NSS is supported.
    586   if (!Aes128Gcm12Encrypter::IsSupported()) {
    587     LOG(INFO) << "AES GCM not supported. Test skipped.";
    588     return;
    589   }
    590 
    591   ASSERT_TRUE(Initialize());
    592 
    593   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
    594   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    595   client_->ResetConnection();
    596   EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
    597   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    598 }
    599 
    600 class WrongAddressWriter : public QuicPacketWriter {
    601  public:
    602   explicit WrongAddressWriter(int fd) : fd_(fd) {
    603     IPAddressNumber ip;
    604     CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip));
    605     self_address_ = IPEndPoint(ip, 0);
    606   }
    607 
    608   virtual int WritePacket(const char* buffer, size_t buf_len,
    609                           const IPAddressNumber& real_self_address,
    610                           const IPEndPoint& peer_address,
    611                           QuicBlockedWriterInterface* blocked_writer,
    612                           int* error) OVERRIDE {
    613     return QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
    614                                         self_address_.address(), peer_address,
    615                                         error);
    616   }
    617 
    618   IPEndPoint self_address_;
    619   int fd_;
    620 };
    621 
    622 TEST_P(EndToEndTest, ConnectionMigration) {
    623   // TODO(rtenneti): Delete this when NSS is supported.
    624   if (!Aes128Gcm12Encrypter::IsSupported()) {
    625     LOG(INFO) << "AES GCM not supported. Test skipped.";
    626     return;
    627   }
    628 
    629   ASSERT_TRUE(Initialize());
    630 
    631   EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
    632   EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
    633 
    634   WrongAddressWriter writer(QuicClientPeer::GetFd(client_->client()));
    635   QuicEpollConnectionHelper* helper =
    636       reinterpret_cast<QuicEpollConnectionHelper*>(
    637           QuicConnectionPeer::GetHelper(
    638               client_->client()->session()->connection()));
    639   QuicEpollConnectionHelperPeer::SetWriter(helper, &writer);
    640 
    641   client_->SendSynchronousRequest("/bar");
    642   QuicEpollConnectionHelperPeer::SetWriter(helper, NULL);
    643 
    644   EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
    645   EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error());
    646 }
    647 
    648 }  // namespace
    649 }  // namespace test
    650 }  // namespace tools
    651 }  // namespace net
    652