• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
HttpProxyClientSocketPoolTest()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 
~HttpProxyClientSocketPoolTest()92   virtual ~HttpProxyClientSocketPoolTest() {
93   }
94 
AddAuthToCache()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 
GetTcpParams()107   scoped_refptr<TransportSocketParams> GetTcpParams() {
108     if (GetParam() != HTTP)
109       return scoped_refptr<TransportSocketParams>();
110     return ignored_transport_socket_params_;
111   }
112 
GetSslParams()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.
GetParams(bool tunnel)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 
GetTunnelParams()135   scoped_refptr<HttpProxySocketParams> GetTunnelParams() {
136     return GetParams(true);
137   }
138 
GetNoTunnelParams()139   scoped_refptr<HttpProxySocketParams> GetNoTunnelParams() {
140     return GetParams(false);
141   }
142 
socket_factory()143   DeterministicMockClientSocketFactory& socket_factory() {
144     return socket_factory_;
145   }
146 
Initialize(bool async,MockRead * reads,size_t reads_count,MockWrite * writes,size_t writes_count,MockRead * spdy_reads,size_t spdy_reads_count,MockWrite * spdy_writes,size_t spdy_writes_count)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 
InitializeSpdySsl()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 
CreateNetworkSession()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 
TEST_P(HttpProxyClientSocketPoolTest,NoTunnel)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 
TEST_P(HttpProxyClientSocketPoolTest,NeedAuth)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 
TEST_P(HttpProxyClientSocketPoolTest,HaveAuth)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 
TEST_P(HttpProxyClientSocketPoolTest,AsyncHaveAuth)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 
TEST_P(HttpProxyClientSocketPoolTest,TCPError)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 
TEST_P(HttpProxyClientSocketPoolTest,SSLError)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 
TEST_P(HttpProxyClientSocketPoolTest,SslClientAuth)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 
TEST_P(HttpProxyClientSocketPoolTest,TunnelUnexpectedClose)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 
TEST_P(HttpProxyClientSocketPoolTest,TunnelSetupError)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