Home | History | Annotate | Download | only in http
      1 // Copyright (c) 2011 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 "net/http/http_proxy_client_socket_pool.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/compiler_specific.h"
      9 #include "base/string_util.h"
     10 #include "base/utf_string_conversions.h"
     11 #include "net/base/mock_host_resolver.h"
     12 #include "net/base/net_errors.h"
     13 #include "net/base/ssl_config_service_defaults.h"
     14 #include "net/base/test_completion_callback.h"
     15 #include "net/http/http_auth_handler_factory.h"
     16 #include "net/http/http_network_session.h"
     17 #include "net/http/http_proxy_client_socket.h"
     18 #include "net/proxy/proxy_service.h"
     19 #include "net/socket/client_socket_handle.h"
     20 #include "net/socket/client_socket_pool_histograms.h"
     21 #include "net/socket/socket_test_util.h"
     22 #include "net/spdy/spdy_protocol.h"
     23 #include "net/spdy/spdy_test_util.h"
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 
     26 namespace net {
     27 
     28 namespace {
     29 
     30 const int kMaxSockets = 32;
     31 const int kMaxSocketsPerGroup = 6;
     32 const char * const kAuthHeaders[] = {
     33   "proxy-authorization", "Basic Zm9vOmJhcg=="
     34 };
     35 const int kAuthHeadersSize = arraysize(kAuthHeaders) / 2;
     36 
     37 enum HttpProxyType {
     38   HTTP,
     39   HTTPS,
     40   SPDY
     41 };
     42 
     43 typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
     44 
     45 }  // namespace
     46 
     47 class HttpProxyClientSocketPoolTest : public TestWithHttpParam {
     48  protected:
     49   HttpProxyClientSocketPoolTest()
     50       : ssl_config_(),
     51         ignored_transport_socket_params_(new TransportSocketParams(
     52             HostPortPair("proxy", 80), LOWEST, GURL(), false, false)),
     53         ignored_ssl_socket_params_(new SSLSocketParams(
     54             ignored_transport_socket_params_, NULL, NULL,
     55             ProxyServer::SCHEME_DIRECT, HostPortPair("www.google.com", 443),
     56             ssl_config_, 0, false, false)),
     57         tcp_histograms_("MockTCP"),
     58         transport_socket_pool_(
     59             kMaxSockets, kMaxSocketsPerGroup,
     60             &tcp_histograms_,
     61             &socket_factory_),
     62         ssl_histograms_("MockSSL"),
     63         proxy_service_(ProxyService::CreateDirect()),
     64         ssl_config_service_(new SSLConfigServiceDefaults),
     65         ssl_socket_pool_(kMaxSockets, kMaxSocketsPerGroup,
     66                          &ssl_histograms_,
     67                          &host_resolver_,
     68                          &cert_verifier_,
     69                          NULL /* dnsrr_resolver */,
     70                          NULL /* dns_cert_checker */,
     71                          NULL /* ssl_host_info_factory */,
     72                          &socket_factory_,
     73                          &transport_socket_pool_,
     74                          NULL,
     75                          NULL,
     76                          ssl_config_service_.get(),
     77                          BoundNetLog().net_log()),
     78         http_auth_handler_factory_(
     79             HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
     80         session_(CreateNetworkSession()),
     81         http_proxy_histograms_("HttpProxyUnitTest"),
     82         ssl_data_(NULL),
     83         data_(NULL),
     84         pool_(kMaxSockets, kMaxSocketsPerGroup,
     85               &http_proxy_histograms_,
     86               NULL,
     87               &transport_socket_pool_,
     88               &ssl_socket_pool_,
     89               NULL) {
     90   }
     91 
     92   virtual ~HttpProxyClientSocketPoolTest() {
     93   }
     94 
     95   void AddAuthToCache() {
     96     const string16 kFoo(ASCIIToUTF16("foo"));
     97     const string16 kBar(ASCIIToUTF16("bar"));
     98     session_->http_auth_cache()->Add(GURL("http://proxy/"),
     99                                      "MyRealm1",
    100                                      HttpAuth::AUTH_SCHEME_BASIC,
    101                                      "Basic realm=MyRealm1",
    102                                      kFoo,
    103                                      kBar,
    104                                      "/");
    105   }
    106 
    107   scoped_refptr<TransportSocketParams> GetTcpParams() {
    108     if (GetParam() != HTTP)
    109       return scoped_refptr<TransportSocketParams>();
    110     return ignored_transport_socket_params_;
    111   }
    112 
    113   scoped_refptr<SSLSocketParams> GetSslParams() {
    114     if (GetParam() == HTTP)
    115       return scoped_refptr<SSLSocketParams>();
    116     return ignored_ssl_socket_params_;
    117   }
    118 
    119   // Returns the a correctly constructed HttpProxyParms
    120   // for the HTTP or HTTPS proxy.
    121   scoped_refptr<HttpProxySocketParams> GetParams(bool tunnel) {
    122     return scoped_refptr<HttpProxySocketParams>(
    123         new HttpProxySocketParams(
    124             GetTcpParams(),
    125             GetSslParams(),
    126             GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
    127             "",
    128             HostPortPair("www.google.com", tunnel ? 443 : 80),
    129             session_->http_auth_cache(),
    130             session_->http_auth_handler_factory(),
    131             session_->spdy_session_pool(),
    132             tunnel));
    133   }
    134 
    135   scoped_refptr<HttpProxySocketParams> GetTunnelParams() {
    136     return GetParams(true);
    137   }
    138 
    139   scoped_refptr<HttpProxySocketParams> GetNoTunnelParams() {
    140     return GetParams(false);
    141   }
    142 
    143   DeterministicMockClientSocketFactory& socket_factory() {
    144     return socket_factory_;
    145   }
    146 
    147   void Initialize(bool async, MockRead* reads, size_t reads_count,
    148                   MockWrite* writes, size_t writes_count,
    149                   MockRead* spdy_reads, size_t spdy_reads_count,
    150                   MockWrite* spdy_writes, size_t spdy_writes_count) {
    151     if (GetParam() == SPDY)
    152       data_ = new DeterministicSocketData(spdy_reads, spdy_reads_count,
    153                                           spdy_writes, spdy_writes_count);
    154     else
    155       data_ = new DeterministicSocketData(reads, reads_count, writes,
    156                                           writes_count);
    157 
    158     data_->set_connect_data(MockConnect(async, 0));
    159     data_->StopAfter(2);  // Request / Response
    160 
    161     socket_factory_.AddSocketDataProvider(data_.get());
    162 
    163     if (GetParam() != HTTP) {
    164       ssl_data_.reset(new SSLSocketDataProvider(async, OK));
    165       if (GetParam() == SPDY) {
    166         InitializeSpdySsl();
    167       }
    168       socket_factory_.AddSSLSocketDataProvider(ssl_data_.get());
    169     }
    170   }
    171 
    172   void InitializeSpdySsl() {
    173     spdy::SpdyFramer::set_enable_compression_default(false);
    174     ssl_data_->next_proto_status = SSLClientSocket::kNextProtoNegotiated;
    175     ssl_data_->next_proto = "spdy/2";
    176     ssl_data_->was_npn_negotiated = true;
    177   }
    178 
    179   HttpNetworkSession* CreateNetworkSession() {
    180     HttpNetworkSession::Params params;
    181     params.host_resolver = &host_resolver_;
    182     params.cert_verifier = &cert_verifier_;
    183     params.proxy_service = proxy_service_;
    184     params.client_socket_factory = &socket_factory_;
    185     params.ssl_config_service = ssl_config_service_;
    186     params.http_auth_handler_factory = http_auth_handler_factory_.get();
    187     return new HttpNetworkSession(params);
    188   }
    189 
    190  private:
    191   SSLConfig ssl_config_;
    192 
    193   scoped_refptr<TransportSocketParams> ignored_transport_socket_params_;
    194   scoped_refptr<SSLSocketParams> ignored_ssl_socket_params_;
    195   ClientSocketPoolHistograms tcp_histograms_;
    196   DeterministicMockClientSocketFactory socket_factory_;
    197   MockTransportClientSocketPool transport_socket_pool_;
    198   ClientSocketPoolHistograms ssl_histograms_;
    199   MockHostResolver host_resolver_;
    200   CertVerifier cert_verifier_;
    201   const scoped_refptr<ProxyService> proxy_service_;
    202   const scoped_refptr<SSLConfigService> ssl_config_service_;
    203   SSLClientSocketPool ssl_socket_pool_;
    204 
    205   const scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory_;
    206   const scoped_refptr<HttpNetworkSession> session_;
    207   ClientSocketPoolHistograms http_proxy_histograms_;
    208 
    209  protected:
    210   scoped_ptr<SSLSocketDataProvider> ssl_data_;
    211   scoped_refptr<DeterministicSocketData> data_;
    212   HttpProxyClientSocketPool pool_;
    213   ClientSocketHandle handle_;
    214   TestCompletionCallback callback_;
    215 };
    216 
    217 //-----------------------------------------------------------------------------
    218 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
    219 // and SPDY.
    220 INSTANTIATE_TEST_CASE_P(HttpProxyClientSocketPoolTests,
    221                         HttpProxyClientSocketPoolTest,
    222                         ::testing::Values(HTTP, HTTPS, SPDY));
    223 
    224 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
    225   Initialize(false, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
    226 
    227   int rv = handle_.Init("a", GetNoTunnelParams(), LOW, NULL, &pool_,
    228                        BoundNetLog());
    229   EXPECT_EQ(OK, rv);
    230   EXPECT_TRUE(handle_.is_initialized());
    231   ASSERT_TRUE(handle_.socket());
    232   HttpProxyClientSocket* tunnel_socket =
    233           static_cast<HttpProxyClientSocket*>(handle_.socket());
    234   EXPECT_TRUE(tunnel_socket->IsConnected());
    235 }
    236 
    237 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
    238   MockWrite writes[] = {
    239     MockWrite(true, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
    240               "Host: www.google.com\r\n"
    241               "Proxy-Connection: keep-alive\r\n\r\n"),
    242   };
    243   MockRead reads[] = {
    244     // No credentials.
    245     MockRead(true, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
    246     MockRead(true, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
    247     MockRead(true, 3, "Content-Length: 10\r\n\r\n"),
    248     MockRead(true, 4, "0123456789"),
    249   };
    250   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(NULL, 0, 1));
    251   scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL));
    252   MockWrite spdy_writes[] = {
    253     CreateMockWrite(*req, 0, true),
    254     CreateMockWrite(*rst, 2, true),
    255   };
    256   scoped_ptr<spdy::SpdyFrame> resp(
    257       ConstructSpdySynReplyError(
    258           "407 Proxy Authentication Required", NULL, 0, 1));
    259   MockRead spdy_reads[] = {
    260     CreateMockWrite(*resp, 1, true),
    261     MockRead(true, 0, 3)
    262   };
    263 
    264   Initialize(false, reads, arraysize(reads), writes, arraysize(writes),
    265              spdy_reads, arraysize(spdy_reads), spdy_writes,
    266              arraysize(spdy_writes));
    267 
    268   data_->StopAfter(4);
    269   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    270                        BoundNetLog());
    271   EXPECT_EQ(ERR_IO_PENDING, rv);
    272   EXPECT_FALSE(handle_.is_initialized());
    273   EXPECT_FALSE(handle_.socket());
    274 
    275   data_->RunFor(4);
    276   rv = callback_.WaitForResult();
    277   if (GetParam() != SPDY) {
    278     EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
    279     EXPECT_TRUE(handle_.is_initialized());
    280     ASSERT_TRUE(handle_.socket());
    281     HttpProxyClientSocket* tunnel_socket =
    282             static_cast<HttpProxyClientSocket*>(handle_.socket());
    283     EXPECT_FALSE(tunnel_socket->IsConnected());
    284     EXPECT_FALSE(tunnel_socket->using_spdy());
    285   } else {
    286     // Proxy auth is not really implemented for SPDY yet
    287     EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
    288     EXPECT_FALSE(handle_.is_initialized());
    289     EXPECT_FALSE(handle_.socket());
    290   }
    291 }
    292 
    293 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
    294   // It's pretty much impossible to make the SPDY case becave synchronously
    295   // so we skip this test for SPDY
    296   if (GetParam() == SPDY)
    297     return;
    298   MockWrite writes[] = {
    299     MockWrite(false, 0,
    300               "CONNECT www.google.com:443 HTTP/1.1\r\n"
    301               "Host: www.google.com\r\n"
    302               "Proxy-Connection: keep-alive\r\n"
    303               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    304   };
    305   MockRead reads[] = {
    306     MockRead(false, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
    307   };
    308 
    309   Initialize(false, reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
    310              NULL, 0);
    311   AddAuthToCache();
    312 
    313   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    314                        BoundNetLog());
    315   EXPECT_EQ(OK, rv);
    316   EXPECT_TRUE(handle_.is_initialized());
    317   ASSERT_TRUE(handle_.socket());
    318   HttpProxyClientSocket* tunnel_socket =
    319           static_cast<HttpProxyClientSocket*>(handle_.socket());
    320   EXPECT_TRUE(tunnel_socket->IsConnected());
    321 }
    322 
    323 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
    324   MockWrite writes[] = {
    325     MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
    326               "Host: www.google.com\r\n"
    327               "Proxy-Connection: keep-alive\r\n"
    328               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    329   };
    330   MockRead reads[] = {
    331     MockRead(false, "HTTP/1.1 200 Connection Established\r\n\r\n"),
    332   };
    333 
    334   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(kAuthHeaders,
    335                                                        kAuthHeadersSize, 1));
    336   MockWrite spdy_writes[] = {
    337     CreateMockWrite(*req, 0, true)
    338   };
    339   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
    340   MockRead spdy_reads[] = {
    341     CreateMockRead(*resp, 1, true),
    342     MockRead(true, 0, 2)
    343   };
    344 
    345   Initialize(false, reads, arraysize(reads), writes, arraysize(writes),
    346              spdy_reads, arraysize(spdy_reads), spdy_writes,
    347              arraysize(spdy_writes));
    348   AddAuthToCache();
    349 
    350   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    351                        BoundNetLog());
    352   EXPECT_EQ(ERR_IO_PENDING, rv);
    353   EXPECT_FALSE(handle_.is_initialized());
    354   EXPECT_FALSE(handle_.socket());
    355 
    356   data_->RunFor(2);
    357   EXPECT_EQ(OK, callback_.WaitForResult());
    358   EXPECT_TRUE(handle_.is_initialized());
    359   ASSERT_TRUE(handle_.socket());
    360   HttpProxyClientSocket* tunnel_socket =
    361           static_cast<HttpProxyClientSocket*>(handle_.socket());
    362   EXPECT_TRUE(tunnel_socket->IsConnected());
    363 }
    364 
    365 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
    366   if (GetParam() == SPDY) return;
    367   data_ = new DeterministicSocketData(NULL, 0, NULL, 0);
    368   data_->set_connect_data(MockConnect(true, ERR_CONNECTION_CLOSED));
    369 
    370   socket_factory().AddSocketDataProvider(data_.get());
    371 
    372   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    373                        BoundNetLog());
    374   EXPECT_EQ(ERR_IO_PENDING, rv);
    375   EXPECT_FALSE(handle_.is_initialized());
    376   EXPECT_FALSE(handle_.socket());
    377 
    378   EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
    379 
    380   EXPECT_FALSE(handle_.is_initialized());
    381   EXPECT_FALSE(handle_.socket());
    382 }
    383 
    384 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
    385   if (GetParam() == HTTP) return;
    386   data_ = new DeterministicSocketData(NULL, 0, NULL, 0);
    387   data_->set_connect_data(MockConnect(true, OK));
    388   socket_factory().AddSocketDataProvider(data_.get());
    389 
    390   ssl_data_.reset(new SSLSocketDataProvider(true,
    391                                             ERR_CERT_AUTHORITY_INVALID));
    392   if (GetParam() == SPDY) {
    393     InitializeSpdySsl();
    394   }
    395   socket_factory().AddSSLSocketDataProvider(ssl_data_.get());
    396 
    397   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    398                         BoundNetLog());
    399   EXPECT_EQ(ERR_IO_PENDING, rv);
    400   EXPECT_FALSE(handle_.is_initialized());
    401   EXPECT_FALSE(handle_.socket());
    402 
    403   EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
    404 
    405   EXPECT_FALSE(handle_.is_initialized());
    406   EXPECT_FALSE(handle_.socket());
    407 }
    408 
    409 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
    410   if (GetParam() == HTTP) return;
    411   data_ = new DeterministicSocketData(NULL, 0, NULL, 0);
    412   data_->set_connect_data(MockConnect(true, OK));
    413   socket_factory().AddSocketDataProvider(data_.get());
    414 
    415   ssl_data_.reset(new SSLSocketDataProvider(true,
    416                                             ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
    417   if (GetParam() == SPDY) {
    418     InitializeSpdySsl();
    419   }
    420   socket_factory().AddSSLSocketDataProvider(ssl_data_.get());
    421 
    422   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    423                        BoundNetLog());
    424   EXPECT_EQ(ERR_IO_PENDING, rv);
    425   EXPECT_FALSE(handle_.is_initialized());
    426   EXPECT_FALSE(handle_.socket());
    427 
    428   EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
    429 
    430   EXPECT_FALSE(handle_.is_initialized());
    431   EXPECT_FALSE(handle_.socket());
    432 }
    433 
    434 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
    435   MockWrite writes[] = {
    436     MockWrite(true, 0,
    437               "CONNECT www.google.com:443 HTTP/1.1\r\n"
    438               "Host: www.google.com\r\n"
    439               "Proxy-Connection: keep-alive\r\n"
    440               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    441   };
    442   MockRead reads[] = {
    443     MockRead(true, 1, "HTTP/1.1 200 Conn"),
    444     MockRead(true, ERR_CONNECTION_CLOSED, 2),
    445   };
    446   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(kAuthHeaders,
    447                                                        kAuthHeadersSize, 1));
    448   MockWrite spdy_writes[] = {
    449     CreateMockWrite(*req, 0, true)
    450   };
    451   MockRead spdy_reads[] = {
    452     MockRead(true, ERR_CONNECTION_CLOSED, 1),
    453   };
    454 
    455   Initialize(false, reads, arraysize(reads), writes, arraysize(writes),
    456              spdy_reads, arraysize(spdy_reads), spdy_writes,
    457              arraysize(spdy_writes));
    458   AddAuthToCache();
    459 
    460   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    461                        BoundNetLog());
    462   EXPECT_EQ(ERR_IO_PENDING, rv);
    463   EXPECT_FALSE(handle_.is_initialized());
    464   EXPECT_FALSE(handle_.socket());
    465 
    466   data_->RunFor(3);
    467   EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
    468   EXPECT_FALSE(handle_.is_initialized());
    469   EXPECT_FALSE(handle_.socket());
    470 }
    471 
    472 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
    473   MockWrite writes[] = {
    474     MockWrite(true, 0,
    475               "CONNECT www.google.com:443 HTTP/1.1\r\n"
    476               "Host: www.google.com\r\n"
    477               "Proxy-Connection: keep-alive\r\n"
    478               "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
    479   };
    480   MockRead reads[] = {
    481     MockRead(true, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
    482   };
    483   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(kAuthHeaders,
    484                                                        kAuthHeadersSize, 1));
    485   scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL));
    486   MockWrite spdy_writes[] = {
    487     CreateMockWrite(*req, 0, true),
    488     CreateMockWrite(*rst, 2, true),
    489   };
    490   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
    491   MockRead spdy_reads[] = {
    492     CreateMockRead(*resp, 1, true),
    493     MockRead(true, 0, 3),
    494   };
    495 
    496   Initialize(false, reads, arraysize(reads), writes, arraysize(writes),
    497              spdy_reads, arraysize(spdy_reads), spdy_writes,
    498              arraysize(spdy_writes));
    499   AddAuthToCache();
    500 
    501   int rv = handle_.Init("a", GetTunnelParams(), LOW, &callback_, &pool_,
    502                        BoundNetLog());
    503   EXPECT_EQ(ERR_IO_PENDING, rv);
    504   EXPECT_FALSE(handle_.is_initialized());
    505   EXPECT_FALSE(handle_.socket());
    506 
    507   data_->RunFor(2);
    508 
    509   rv = callback_.WaitForResult();
    510   if (GetParam() == HTTP) {
    511     // HTTP Proxy CONNECT responses are not trustworthy
    512     EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
    513     EXPECT_FALSE(handle_.is_initialized());
    514     EXPECT_FALSE(handle_.socket());
    515   } else {
    516     // HTTPS or SPDY Proxy CONNECT responses are trustworthy
    517     EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
    518     EXPECT_TRUE(handle_.is_initialized());
    519     EXPECT_TRUE(handle_.socket());
    520   }
    521 }
    522 
    523 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
    524 
    525 }  // namespace net
    526