Mark two tests in ImeTest.java as flaky
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blob909da6233eb9307711402f3482ab99debe01e1a3
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.
5 #include "net/http/http_proxy_client_socket_pool.h"
7 #include "base/callback.h"
8 #include "base/compiler_specific.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/proxy_delegate.h"
13 #include "net/base/test_completion_callback.h"
14 #include "net/http/http_network_session.h"
15 #include "net/http/http_proxy_client_socket.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/socket/client_socket_handle.h"
18 #include "net/socket/client_socket_pool_histograms.h"
19 #include "net/socket/next_proto.h"
20 #include "net/socket/socket_test_util.h"
21 #include "net/spdy/spdy_protocol.h"
22 #include "net/spdy/spdy_test_util_common.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 namespace net {
27 namespace {
29 const int kMaxSockets = 32;
30 const int kMaxSocketsPerGroup = 6;
31 const char * const kAuthHeaders[] = {
32 "proxy-authorization", "Basic Zm9vOmJhcg=="
34 const int kAuthHeadersSize = arraysize(kAuthHeaders) / 2;
36 enum HttpProxyType {
37 HTTP,
38 HTTPS,
39 SPDY
42 struct HttpProxyClientSocketPoolTestParams {
43 HttpProxyClientSocketPoolTestParams()
44 : proxy_type(HTTP),
45 protocol(kProtoSPDY31) {}
47 HttpProxyClientSocketPoolTestParams(
48 HttpProxyType proxy_type,
49 NextProto protocol)
50 : proxy_type(proxy_type),
51 protocol(protocol) {}
53 HttpProxyType proxy_type;
54 NextProto protocol;
57 typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
59 const char kHttpProxyHost[] = "httpproxy.example.com";
60 const char kHttpsProxyHost[] = "httpsproxy.example.com";
62 class TestProxyDelegate : public ProxyDelegate {
63 public:
64 TestProxyDelegate()
65 : on_before_tunnel_request_called_(false),
66 on_tunnel_request_completed_called_(false),
67 on_tunnel_headers_received_called_(false) {
70 ~TestProxyDelegate() override {}
72 bool on_before_tunnel_request_called() const {
73 return on_before_tunnel_request_called_;
76 bool on_tunnel_request_completed_called() const {
77 return on_tunnel_request_completed_called_;
80 bool on_tunnel_headers_received_called() const {
81 return on_tunnel_headers_received_called_;
84 void VerifyOnTunnelRequestCompleted(const std::string& endpoint,
85 const std::string& proxy_server) const {
86 EXPECT_TRUE(on_tunnel_request_completed_called_);
87 EXPECT_TRUE(HostPortPair::FromString(endpoint).Equals(
88 on_tunnel_request_completed_endpoint_));
89 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
90 on_tunnel_request_completed_proxy_server_));
93 void VerifyOnTunnelHeadersReceived(const std::string& origin,
94 const std::string& proxy_server,
95 const std::string& status_line) const {
96 EXPECT_TRUE(on_tunnel_headers_received_called_);
97 EXPECT_TRUE(HostPortPair::FromString(origin).Equals(
98 on_tunnel_headers_received_origin_));
99 EXPECT_TRUE(HostPortPair::FromString(proxy_server).Equals(
100 on_tunnel_headers_received_proxy_server_));
101 EXPECT_EQ(status_line, on_tunnel_headers_received_status_line_);
104 // ProxyDelegate:
105 void OnResolveProxy(const GURL& url,
106 int load_flags,
107 const ProxyService& proxy_service,
108 ProxyInfo* result) override {}
110 void OnTunnelConnectCompleted(const HostPortPair& endpoint,
111 const HostPortPair& proxy_server,
112 int net_error) override {
113 on_tunnel_request_completed_called_ = true;
114 on_tunnel_request_completed_endpoint_ = endpoint;
115 on_tunnel_request_completed_proxy_server_ = proxy_server;
118 void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
120 void OnBeforeSendHeaders(URLRequest* request,
121 const ProxyInfo& proxy_info,
122 HttpRequestHeaders* headers) override {}
124 void OnBeforeTunnelRequest(const net::HostPortPair& proxy_server,
125 net::HttpRequestHeaders* extra_headers) override {
126 on_before_tunnel_request_called_ = true;
127 if (extra_headers) {
128 extra_headers->SetHeader("Foo", proxy_server.ToString());
132 void OnTunnelHeadersReceived(
133 const net::HostPortPair& origin,
134 const net::HostPortPair& proxy_server,
135 const net::HttpResponseHeaders& response_headers) override {
136 on_tunnel_headers_received_called_ = true;
137 on_tunnel_headers_received_origin_ = origin;
138 on_tunnel_headers_received_proxy_server_ = proxy_server;
139 on_tunnel_headers_received_status_line_ = response_headers.GetStatusLine();
142 private:
143 bool on_before_tunnel_request_called_;
144 bool on_tunnel_request_completed_called_;
145 bool on_tunnel_headers_received_called_;
146 HostPortPair on_tunnel_request_completed_endpoint_;
147 HostPortPair on_tunnel_request_completed_proxy_server_;
148 HostPortPair on_tunnel_headers_received_origin_;
149 HostPortPair on_tunnel_headers_received_proxy_server_;
150 std::string on_tunnel_headers_received_status_line_;
154 class HttpProxyClientSocketPoolTest
155 : public ::testing::TestWithParam<HttpProxyClientSocketPoolTestParams> {
156 protected:
157 HttpProxyClientSocketPoolTest()
158 : session_deps_(GetParam().protocol),
159 tcp_histograms_("MockTCP"),
160 transport_socket_pool_(
161 kMaxSockets,
162 kMaxSocketsPerGroup,
163 &tcp_histograms_,
164 session_deps_.deterministic_socket_factory.get()),
165 ssl_histograms_("MockSSL"),
166 ssl_socket_pool_(kMaxSockets,
167 kMaxSocketsPerGroup,
168 &ssl_histograms_,
169 session_deps_.host_resolver.get(),
170 session_deps_.cert_verifier.get(),
171 NULL /* channel_id_store */,
172 NULL /* transport_security_state */,
173 NULL /* cert_transparency_verifier */,
174 NULL /* cert_policy_enforcer */,
175 std::string() /* ssl_session_cache_shard */,
176 session_deps_.deterministic_socket_factory.get(),
177 &transport_socket_pool_,
178 NULL,
179 NULL,
180 session_deps_.ssl_config_service.get(),
181 false,
182 BoundNetLog().net_log()),
183 session_(CreateNetworkSession()),
184 http_proxy_histograms_("HttpProxyUnitTest"),
185 spdy_util_(GetParam().protocol),
186 pool_(kMaxSockets,
187 kMaxSocketsPerGroup,
188 &http_proxy_histograms_,
189 NULL,
190 &transport_socket_pool_,
191 &ssl_socket_pool_,
192 NULL,
193 NULL) {}
195 virtual ~HttpProxyClientSocketPoolTest() {
198 void AddAuthToCache() {
199 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
200 const base::string16 kBar(base::ASCIIToUTF16("bar"));
201 GURL proxy_url(GetParam().proxy_type == HTTP ?
202 (std::string("http://") + kHttpProxyHost) :
203 (std::string("https://") + kHttpsProxyHost));
204 session_->http_auth_cache()->Add(proxy_url,
205 "MyRealm1",
206 HttpAuth::AUTH_SCHEME_BASIC,
207 "Basic realm=MyRealm1",
208 AuthCredentials(kFoo, kBar),
209 "/");
212 scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
213 if (GetParam().proxy_type != HTTP)
214 return NULL;
215 return new TransportSocketParams(
216 HostPortPair(kHttpProxyHost, 80),
217 false,
218 false,
219 OnHostResolutionCallback(),
220 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);
223 scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
224 if (GetParam().proxy_type == HTTP)
225 return NULL;
226 return new SSLSocketParams(
227 new TransportSocketParams(
228 HostPortPair(kHttpsProxyHost, 443),
229 false,
230 false,
231 OnHostResolutionCallback(),
232 TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT),
233 NULL,
234 NULL,
235 HostPortPair(kHttpsProxyHost, 443),
236 SSLConfig(),
237 PRIVACY_MODE_DISABLED,
239 false,
240 false);
243 // Returns the a correctly constructed HttpProxyParms
244 // for the HTTP or HTTPS proxy.
245 scoped_refptr<HttpProxySocketParams> CreateParams(
246 bool tunnel,
247 ProxyDelegate* proxy_delegate) {
248 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
249 CreateHttpProxyParams(),
250 CreateHttpsProxyParams(),
251 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
252 std::string(),
253 HostPortPair("www.google.com", tunnel ? 443 : 80),
254 session_->http_auth_cache(),
255 session_->http_auth_handler_factory(),
256 session_->spdy_session_pool(),
257 tunnel,
258 proxy_delegate));
261 scoped_refptr<HttpProxySocketParams> CreateTunnelParams(
262 ProxyDelegate* proxy_delegate) {
263 return CreateParams(true, proxy_delegate);
266 scoped_refptr<HttpProxySocketParams> CreateNoTunnelParams(
267 ProxyDelegate* proxy_delegate) {
268 return CreateParams(false, proxy_delegate);
271 DeterministicMockClientSocketFactory* socket_factory() {
272 return session_deps_.deterministic_socket_factory.get();
275 void Initialize(MockRead* reads, size_t reads_count,
276 MockWrite* writes, size_t writes_count,
277 MockRead* spdy_reads, size_t spdy_reads_count,
278 MockWrite* spdy_writes, size_t spdy_writes_count) {
279 if (GetParam().proxy_type == SPDY) {
280 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
281 spdy_writes, spdy_writes_count));
282 } else {
283 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
284 writes_count));
287 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
288 data_->StopAfter(2); // Request / Response
290 socket_factory()->AddSocketDataProvider(data_.get());
292 if (GetParam().proxy_type != HTTP) {
293 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
294 if (GetParam().proxy_type == SPDY) {
295 InitializeSpdySsl();
297 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
301 void InitializeSpdySsl() {
302 ssl_data_->SetNextProto(GetParam().protocol);
305 HttpNetworkSession* CreateNetworkSession() {
306 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
307 &session_deps_);
310 RequestPriority GetLastTransportRequestPriority() const {
311 return transport_socket_pool_.last_request_priority();
314 private:
315 SpdySessionDependencies session_deps_;
317 ClientSocketPoolHistograms tcp_histograms_;
318 MockTransportClientSocketPool transport_socket_pool_;
319 ClientSocketPoolHistograms ssl_histograms_;
320 MockHostResolver host_resolver_;
321 scoped_ptr<CertVerifier> cert_verifier_;
322 SSLClientSocketPool ssl_socket_pool_;
324 const scoped_refptr<HttpNetworkSession> session_;
325 ClientSocketPoolHistograms http_proxy_histograms_;
327 protected:
328 SpdyTestUtil spdy_util_;
329 scoped_ptr<SSLSocketDataProvider> ssl_data_;
330 scoped_ptr<DeterministicSocketData> data_;
331 HttpProxyClientSocketPool pool_;
332 ClientSocketHandle handle_;
333 TestCompletionCallback callback_;
336 //-----------------------------------------------------------------------------
337 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
338 // and SPDY.
340 // TODO(akalin): Use ::testing::Combine() when we are able to use
341 // <tr1/tuple>.
342 INSTANTIATE_TEST_CASE_P(
343 HttpProxyClientSocketPoolTests,
344 HttpProxyClientSocketPoolTest,
345 ::testing::Values(
346 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
347 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
348 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
349 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4_14),
350 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4_14),
351 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4_14),
352 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4_15),
353 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4_15),
354 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4_15)));
356 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
357 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
359 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
360 int rv = handle_.Init("a", CreateNoTunnelParams(proxy_delegate.get()), LOW,
361 CompletionCallback(), &pool_, BoundNetLog());
362 EXPECT_EQ(OK, rv);
363 EXPECT_TRUE(handle_.is_initialized());
364 ASSERT_TRUE(handle_.socket());
365 HttpProxyClientSocket* tunnel_socket =
366 static_cast<HttpProxyClientSocket*>(handle_.socket());
367 EXPECT_TRUE(tunnel_socket->IsConnected());
368 EXPECT_FALSE(proxy_delegate->on_before_tunnel_request_called());
369 EXPECT_FALSE(proxy_delegate->on_tunnel_headers_received_called());
370 EXPECT_TRUE(proxy_delegate->on_tunnel_request_completed_called());
373 // Make sure that HttpProxyConnectJob passes on its priority to its
374 // (non-SSL) socket request on Init.
375 TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
376 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
377 EXPECT_EQ(OK,
378 handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST,
379 CompletionCallback(), &pool_, BoundNetLog()));
380 EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
383 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
384 MockWrite writes[] = {
385 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
386 "Host: www.google.com\r\n"
387 "Proxy-Connection: keep-alive\r\n\r\n"),
389 MockRead reads[] = {
390 // No credentials.
391 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
392 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
393 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
394 MockRead(ASYNC, 4, "0123456789"),
396 scoped_ptr<SpdyFrame> req(spdy_util_.ConstructSpdyConnect(
397 NULL, 0, 1, LOW, HostPortPair("www.google.com", 443)));
398 scoped_ptr<SpdyFrame> rst(
399 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
400 MockWrite spdy_writes[] = {
401 CreateMockWrite(*req, 0, ASYNC),
402 CreateMockWrite(*rst, 2, ASYNC),
404 SpdyHeaderBlock resp_block;
405 resp_block[spdy_util_.GetStatusKey()] = "407";
406 resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
407 spdy_util_.MaybeAddVersionHeader(&resp_block);
409 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
410 MockRead spdy_reads[] = {
411 CreateMockRead(*resp, 1, ASYNC),
412 MockRead(ASYNC, 0, 3)
415 Initialize(reads, arraysize(reads), writes, arraysize(writes),
416 spdy_reads, arraysize(spdy_reads), spdy_writes,
417 arraysize(spdy_writes));
419 data_->StopAfter(4);
420 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
421 callback_.callback(), &pool_, BoundNetLog());
422 EXPECT_EQ(ERR_IO_PENDING, rv);
423 EXPECT_FALSE(handle_.is_initialized());
424 EXPECT_FALSE(handle_.socket());
426 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
427 rv = callback_.WaitForResult();
428 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
429 EXPECT_TRUE(handle_.is_initialized());
430 ASSERT_TRUE(handle_.socket());
431 ProxyClientSocket* tunnel_socket =
432 static_cast<ProxyClientSocket*>(handle_.socket());
433 if (GetParam().proxy_type == SPDY) {
434 EXPECT_TRUE(tunnel_socket->IsConnected());
435 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
436 } else {
437 EXPECT_FALSE(tunnel_socket->IsConnected());
438 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
442 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
443 // It's pretty much impossible to make the SPDY case behave synchronously
444 // so we skip this test for SPDY
445 if (GetParam().proxy_type == SPDY)
446 return;
447 std::string proxy_host_port =
448 GetParam().proxy_type == HTTP ?
449 (kHttpProxyHost + std::string(":80")) :
450 (kHttpsProxyHost + std::string(":443"));
451 std::string request =
452 "CONNECT www.google.com:443 HTTP/1.1\r\n"
453 "Host: www.google.com\r\n"
454 "Proxy-Connection: keep-alive\r\n"
455 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
456 "Foo: " + proxy_host_port + "\r\n\r\n";
457 MockWrite writes[] = {
458 MockWrite(SYNCHRONOUS, 0, request.c_str()),
460 MockRead reads[] = {
461 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
464 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
465 NULL, 0);
466 AddAuthToCache();
468 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
469 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
470 callback_.callback(), &pool_, BoundNetLog());
471 EXPECT_EQ(OK, rv);
472 EXPECT_TRUE(handle_.is_initialized());
473 ASSERT_TRUE(handle_.socket());
474 HttpProxyClientSocket* tunnel_socket =
475 static_cast<HttpProxyClientSocket*>(handle_.socket());
476 EXPECT_TRUE(tunnel_socket->IsConnected());
477 proxy_delegate->VerifyOnTunnelHeadersReceived(
478 "www.google.com:443",
479 proxy_host_port.c_str(),
480 "HTTP/1.1 200 Connection Established");
481 proxy_delegate->VerifyOnTunnelRequestCompleted(
482 "www.google.com:443",
483 proxy_host_port.c_str());
486 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
487 std::string proxy_host_port =
488 GetParam().proxy_type == HTTP ?
489 (kHttpProxyHost + std::string(":80")) :
490 (kHttpsProxyHost + std::string(":443"));
491 std::string request =
492 "CONNECT www.google.com:443 HTTP/1.1\r\n"
493 "Host: www.google.com\r\n"
494 "Proxy-Connection: keep-alive\r\n"
495 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
496 "Foo: " + proxy_host_port + "\r\n\r\n";
497 MockWrite writes[] = {
498 MockWrite(ASYNC, 0, request.c_str()),
500 MockRead reads[] = {
501 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
504 scoped_ptr<SpdyFrame> req(
505 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
506 HostPortPair("www.google.com", 443)));
507 MockWrite spdy_writes[] = {
508 CreateMockWrite(*req, 0, ASYNC)
510 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
511 MockRead spdy_reads[] = {
512 CreateMockRead(*resp, 1, ASYNC),
513 MockRead(ASYNC, 0, 2)
516 Initialize(reads, arraysize(reads), writes, arraysize(writes),
517 spdy_reads, arraysize(spdy_reads), spdy_writes,
518 arraysize(spdy_writes));
519 AddAuthToCache();
521 scoped_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate());
522 int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW,
523 callback_.callback(), &pool_, BoundNetLog());
524 EXPECT_EQ(ERR_IO_PENDING, rv);
525 EXPECT_FALSE(handle_.is_initialized());
526 EXPECT_FALSE(handle_.socket());
528 data_->RunFor(2);
529 EXPECT_EQ(OK, callback_.WaitForResult());
530 EXPECT_TRUE(handle_.is_initialized());
531 ASSERT_TRUE(handle_.socket());
532 HttpProxyClientSocket* tunnel_socket =
533 static_cast<HttpProxyClientSocket*>(handle_.socket());
534 EXPECT_TRUE(tunnel_socket->IsConnected());
535 proxy_delegate->VerifyOnTunnelRequestCompleted(
536 "www.google.com:443",
537 proxy_host_port.c_str());
540 // Make sure that HttpProxyConnectJob passes on its priority to its
541 // SPDY session's socket request on Init (if applicable).
542 TEST_P(HttpProxyClientSocketPoolTest,
543 SetSpdySessionSocketRequestPriorityOnInit) {
544 if (GetParam().proxy_type != SPDY)
545 return;
547 scoped_ptr<SpdyFrame> req(
548 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, MEDIUM,
549 HostPortPair("www.google.com", 443)));
550 MockWrite spdy_writes[] = {
551 CreateMockWrite(*req, 0, ASYNC)
553 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
554 MockRead spdy_reads[] = {
555 CreateMockRead(*resp, 1, ASYNC),
556 MockRead(ASYNC, 0, 2)
559 Initialize(NULL, 0, NULL, 0,
560 spdy_reads, arraysize(spdy_reads),
561 spdy_writes, arraysize(spdy_writes));
562 AddAuthToCache();
564 EXPECT_EQ(ERR_IO_PENDING,
565 handle_.Init("a", CreateTunnelParams(NULL), MEDIUM,
566 callback_.callback(), &pool_, BoundNetLog()));
567 EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
569 data_->RunFor(2);
570 EXPECT_EQ(OK, callback_.WaitForResult());
573 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
574 if (GetParam().proxy_type == SPDY) return;
575 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
576 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
578 socket_factory()->AddSocketDataProvider(data_.get());
580 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
581 callback_.callback(), &pool_, BoundNetLog());
582 EXPECT_EQ(ERR_IO_PENDING, rv);
583 EXPECT_FALSE(handle_.is_initialized());
584 EXPECT_FALSE(handle_.socket());
586 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
588 EXPECT_FALSE(handle_.is_initialized());
589 EXPECT_FALSE(handle_.socket());
592 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
593 if (GetParam().proxy_type == HTTP) return;
594 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
595 data_->set_connect_data(MockConnect(ASYNC, OK));
596 socket_factory()->AddSocketDataProvider(data_.get());
598 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
599 ERR_CERT_AUTHORITY_INVALID));
600 if (GetParam().proxy_type == SPDY) {
601 InitializeSpdySsl();
603 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
605 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
606 callback_.callback(), &pool_, BoundNetLog());
607 EXPECT_EQ(ERR_IO_PENDING, rv);
608 EXPECT_FALSE(handle_.is_initialized());
609 EXPECT_FALSE(handle_.socket());
611 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
613 EXPECT_FALSE(handle_.is_initialized());
614 EXPECT_FALSE(handle_.socket());
617 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
618 if (GetParam().proxy_type == HTTP) return;
619 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
620 data_->set_connect_data(MockConnect(ASYNC, OK));
621 socket_factory()->AddSocketDataProvider(data_.get());
623 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
624 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
625 if (GetParam().proxy_type == SPDY) {
626 InitializeSpdySsl();
628 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
630 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
631 callback_.callback(), &pool_, BoundNetLog());
632 EXPECT_EQ(ERR_IO_PENDING, rv);
633 EXPECT_FALSE(handle_.is_initialized());
634 EXPECT_FALSE(handle_.socket());
636 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
638 EXPECT_FALSE(handle_.is_initialized());
639 EXPECT_FALSE(handle_.socket());
642 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
643 MockWrite writes[] = {
644 MockWrite(ASYNC, 0,
645 "CONNECT www.google.com:443 HTTP/1.1\r\n"
646 "Host: www.google.com\r\n"
647 "Proxy-Connection: keep-alive\r\n"
648 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
650 MockRead reads[] = {
651 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
652 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
654 scoped_ptr<SpdyFrame> req(
655 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
656 HostPortPair("www.google.com", 443)));
657 MockWrite spdy_writes[] = {
658 CreateMockWrite(*req, 0, ASYNC)
660 MockRead spdy_reads[] = {
661 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
664 Initialize(reads, arraysize(reads), writes, arraysize(writes),
665 spdy_reads, arraysize(spdy_reads), spdy_writes,
666 arraysize(spdy_writes));
667 AddAuthToCache();
669 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
670 callback_.callback(), &pool_, BoundNetLog());
671 EXPECT_EQ(ERR_IO_PENDING, rv);
672 EXPECT_FALSE(handle_.is_initialized());
673 EXPECT_FALSE(handle_.socket());
675 data_->RunFor(3);
676 if (GetParam().proxy_type == SPDY) {
677 // SPDY cannot process a headers block unless it's complete and so it
678 // returns ERR_CONNECTION_CLOSED in this case.
679 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
680 } else {
681 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
683 EXPECT_FALSE(handle_.is_initialized());
684 EXPECT_FALSE(handle_.socket());
687 TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
688 // Tests that 1xx responses are rejected for a CONNECT request.
689 if (GetParam().proxy_type == SPDY) {
690 // SPDY doesn't have 1xx responses.
691 return;
694 MockWrite writes[] = {
695 MockWrite(ASYNC, 0,
696 "CONNECT www.google.com:443 HTTP/1.1\r\n"
697 "Host: www.google.com\r\n"
698 "Proxy-Connection: keep-alive\r\n\r\n"),
700 MockRead reads[] = {
701 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
702 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
705 Initialize(reads, arraysize(reads), writes, arraysize(writes),
706 NULL, 0, NULL, 0);
708 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
709 callback_.callback(), &pool_, BoundNetLog());
710 EXPECT_EQ(ERR_IO_PENDING, rv);
711 EXPECT_FALSE(handle_.is_initialized());
712 EXPECT_FALSE(handle_.socket());
714 data_->RunFor(2);
715 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
718 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
719 MockWrite writes[] = {
720 MockWrite(ASYNC, 0,
721 "CONNECT www.google.com:443 HTTP/1.1\r\n"
722 "Host: www.google.com\r\n"
723 "Proxy-Connection: keep-alive\r\n"
724 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
726 MockRead reads[] = {
727 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
729 scoped_ptr<SpdyFrame> req(
730 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
731 HostPortPair("www.google.com", 443)));
732 scoped_ptr<SpdyFrame> rst(
733 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
734 MockWrite spdy_writes[] = {
735 CreateMockWrite(*req, 0, ASYNC),
736 CreateMockWrite(*rst, 2, ASYNC),
738 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
739 MockRead spdy_reads[] = {
740 CreateMockRead(*resp, 1, ASYNC),
741 MockRead(ASYNC, 0, 3),
744 Initialize(reads, arraysize(reads), writes, arraysize(writes),
745 spdy_reads, arraysize(spdy_reads), spdy_writes,
746 arraysize(spdy_writes));
747 AddAuthToCache();
749 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
750 callback_.callback(), &pool_, BoundNetLog());
751 EXPECT_EQ(ERR_IO_PENDING, rv);
752 EXPECT_FALSE(handle_.is_initialized());
753 EXPECT_FALSE(handle_.socket());
755 data_->RunFor(2);
757 rv = callback_.WaitForResult();
758 // All Proxy CONNECT responses are not trustworthy
759 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
760 EXPECT_FALSE(handle_.is_initialized());
761 EXPECT_FALSE(handle_.socket());
764 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
765 const std::string redirectTarget = "https://foo.google.com/";
767 const std::string responseText = "HTTP/1.1 302 Found\r\n"
768 "Location: " + redirectTarget + "\r\n"
769 "Set-Cookie: foo=bar\r\n"
770 "\r\n";
771 MockWrite writes[] = {
772 MockWrite(ASYNC, 0,
773 "CONNECT www.google.com:443 HTTP/1.1\r\n"
774 "Host: www.google.com\r\n"
775 "Proxy-Connection: keep-alive\r\n"
776 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
778 MockRead reads[] = {
779 MockRead(ASYNC, 1, responseText.c_str()),
781 scoped_ptr<SpdyFrame> req(
782 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW,
783 HostPortPair("www.google.com", 443)));
784 scoped_ptr<SpdyFrame> rst(
785 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
787 MockWrite spdy_writes[] = {
788 CreateMockWrite(*req, 0, ASYNC),
789 CreateMockWrite(*rst, 3, ASYNC),
792 const char* const responseHeaders[] = {
793 "location", redirectTarget.c_str(),
794 "set-cookie", "foo=bar",
796 const int responseHeadersSize = arraysize(responseHeaders) / 2;
797 scoped_ptr<SpdyFrame> resp(
798 spdy_util_.ConstructSpdySynReplyError(
799 "302 Found",
800 responseHeaders, responseHeadersSize,
801 1));
802 MockRead spdy_reads[] = {
803 CreateMockRead(*resp, 1, ASYNC),
804 MockRead(ASYNC, 0, 2),
807 Initialize(reads, arraysize(reads), writes, arraysize(writes),
808 spdy_reads, arraysize(spdy_reads), spdy_writes,
809 arraysize(spdy_writes));
810 AddAuthToCache();
812 int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW,
813 callback_.callback(), &pool_, BoundNetLog());
814 EXPECT_EQ(ERR_IO_PENDING, rv);
815 EXPECT_FALSE(handle_.is_initialized());
816 EXPECT_FALSE(handle_.socket());
818 data_->RunFor(2);
820 rv = callback_.WaitForResult();
822 if (GetParam().proxy_type == HTTP) {
823 // We don't trust 302 responses to CONNECT from HTTP proxies.
824 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
825 EXPECT_FALSE(handle_.is_initialized());
826 EXPECT_FALSE(handle_.socket());
827 } else {
828 // Expect ProxyClientSocket to return the proxy's response, sanitized.
829 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
830 EXPECT_TRUE(handle_.is_initialized());
831 ASSERT_TRUE(handle_.socket());
833 const ProxyClientSocket* tunnel_socket =
834 static_cast<ProxyClientSocket*>(handle_.socket());
835 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
836 const HttpResponseHeaders* headers = response->headers.get();
838 // Make sure Set-Cookie header was stripped.
839 EXPECT_FALSE(headers->HasHeader("set-cookie"));
841 // Make sure Content-Length: 0 header was added.
842 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
844 // Make sure Location header was included and correct.
845 std::string location;
846 EXPECT_TRUE(headers->IsRedirect(&location));
847 EXPECT_EQ(location, redirectTarget);
851 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
853 } // namespace
855 } // namespace net