Probably broke Win7 Tests (dbg)(6). http://build.chromium.org/p/chromium.win/builders...
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blob0198b05b0c8ebf614b821af2be13703111e8c0dc
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/test_completion_callback.h"
13 #include "net/http/http_network_session.h"
14 #include "net/http/http_proxy_client_socket.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/socket/client_socket_handle.h"
17 #include "net/socket/client_socket_pool_histograms.h"
18 #include "net/socket/next_proto.h"
19 #include "net/socket/socket_test_util.h"
20 #include "net/spdy/spdy_protocol.h"
21 #include "net/spdy/spdy_test_util_common.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 namespace net {
26 namespace {
28 const int kMaxSockets = 32;
29 const int kMaxSocketsPerGroup = 6;
30 const char * const kAuthHeaders[] = {
31 "proxy-authorization", "Basic Zm9vOmJhcg=="
33 const int kAuthHeadersSize = arraysize(kAuthHeaders) / 2;
35 enum HttpProxyType {
36 HTTP,
37 HTTPS,
38 SPDY
41 struct HttpProxyClientSocketPoolTestParams {
42 HttpProxyClientSocketPoolTestParams()
43 : proxy_type(HTTP),
44 protocol(kProtoSPDY3) {}
46 HttpProxyClientSocketPoolTestParams(
47 HttpProxyType proxy_type,
48 NextProto protocol)
49 : proxy_type(proxy_type),
50 protocol(protocol) {}
52 HttpProxyType proxy_type;
53 NextProto protocol;
56 typedef ::testing::TestWithParam<HttpProxyType> TestWithHttpParam;
58 const char kHttpProxyHost[] = "httpproxy.example.com";
59 const char kHttpsProxyHost[] = "httpsproxy.example.com";
61 class HttpProxyClientSocketPoolTest
62 : public ::testing::TestWithParam<HttpProxyClientSocketPoolTestParams> {
63 protected:
64 HttpProxyClientSocketPoolTest()
65 : session_deps_(GetParam().protocol),
66 tcp_histograms_("MockTCP"),
67 transport_socket_pool_(
68 kMaxSockets,
69 kMaxSocketsPerGroup,
70 &tcp_histograms_,
71 session_deps_.deterministic_socket_factory.get()),
72 ssl_histograms_("MockSSL"),
73 ssl_socket_pool_(kMaxSockets,
74 kMaxSocketsPerGroup,
75 &ssl_histograms_,
76 session_deps_.host_resolver.get(),
77 session_deps_.cert_verifier.get(),
78 NULL /* server_bound_cert_store */,
79 NULL /* transport_security_state */,
80 NULL /* cert_transparency_verifier */,
81 std::string() /* ssl_session_cache_shard */,
82 session_deps_.deterministic_socket_factory.get(),
83 &transport_socket_pool_,
84 NULL,
85 NULL,
86 session_deps_.ssl_config_service.get(),
87 BoundNetLog().net_log()),
88 session_(CreateNetworkSession()),
89 http_proxy_histograms_("HttpProxyUnitTest"),
90 spdy_util_(GetParam().protocol),
91 pool_(kMaxSockets,
92 kMaxSocketsPerGroup,
93 &http_proxy_histograms_,
94 NULL,
95 &transport_socket_pool_,
96 &ssl_socket_pool_,
97 NULL) {}
99 virtual ~HttpProxyClientSocketPoolTest() {
102 void AddAuthToCache() {
103 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
104 const base::string16 kBar(base::ASCIIToUTF16("bar"));
105 GURL proxy_url(GetParam().proxy_type == HTTP ?
106 (std::string("http://") + kHttpProxyHost) :
107 (std::string("https://") + kHttpsProxyHost));
108 session_->http_auth_cache()->Add(proxy_url,
109 "MyRealm1",
110 HttpAuth::AUTH_SCHEME_BASIC,
111 "Basic realm=MyRealm1",
112 AuthCredentials(kFoo, kBar),
113 "/");
116 scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
117 if (GetParam().proxy_type != HTTP)
118 return NULL;
119 return new TransportSocketParams(HostPortPair(kHttpProxyHost, 80),
120 false,
121 false,
122 OnHostResolutionCallback());
125 scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
126 if (GetParam().proxy_type == HTTP)
127 return NULL;
128 return new SSLSocketParams(
129 new TransportSocketParams(
130 HostPortPair(kHttpsProxyHost, 443),
131 false,
132 false,
133 OnHostResolutionCallback()),
134 NULL,
135 NULL,
136 HostPortPair(kHttpsProxyHost, 443),
137 SSLConfig(),
138 PRIVACY_MODE_DISABLED,
140 false,
141 false);
144 // Returns the a correctly constructed HttpProxyParms
145 // for the HTTP or HTTPS proxy.
146 scoped_refptr<HttpProxySocketParams> CreateParams(bool tunnel) {
147 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
148 CreateHttpProxyParams(),
149 CreateHttpsProxyParams(),
150 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
151 std::string(),
152 HostPortPair("www.google.com", tunnel ? 443 : 80),
153 session_->http_auth_cache(),
154 session_->http_auth_handler_factory(),
155 session_->spdy_session_pool(),
156 tunnel));
159 scoped_refptr<HttpProxySocketParams> CreateTunnelParams() {
160 return CreateParams(true);
163 scoped_refptr<HttpProxySocketParams> CreateNoTunnelParams() {
164 return CreateParams(false);
167 DeterministicMockClientSocketFactory* socket_factory() {
168 return session_deps_.deterministic_socket_factory.get();
171 void Initialize(MockRead* reads, size_t reads_count,
172 MockWrite* writes, size_t writes_count,
173 MockRead* spdy_reads, size_t spdy_reads_count,
174 MockWrite* spdy_writes, size_t spdy_writes_count) {
175 if (GetParam().proxy_type == SPDY) {
176 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
177 spdy_writes, spdy_writes_count));
178 } else {
179 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
180 writes_count));
183 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
184 data_->StopAfter(2); // Request / Response
186 socket_factory()->AddSocketDataProvider(data_.get());
188 if (GetParam().proxy_type != HTTP) {
189 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
190 if (GetParam().proxy_type == SPDY) {
191 InitializeSpdySsl();
193 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
197 void InitializeSpdySsl() {
198 ssl_data_->SetNextProto(GetParam().protocol);
201 HttpNetworkSession* CreateNetworkSession() {
202 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
203 &session_deps_);
206 RequestPriority GetLastTransportRequestPriority() const {
207 return transport_socket_pool_.last_request_priority();
210 private:
211 SpdySessionDependencies session_deps_;
213 ClientSocketPoolHistograms tcp_histograms_;
214 MockTransportClientSocketPool transport_socket_pool_;
215 ClientSocketPoolHistograms ssl_histograms_;
216 MockHostResolver host_resolver_;
217 scoped_ptr<CertVerifier> cert_verifier_;
218 SSLClientSocketPool ssl_socket_pool_;
220 const scoped_refptr<HttpNetworkSession> session_;
221 ClientSocketPoolHistograms http_proxy_histograms_;
223 protected:
224 SpdyTestUtil spdy_util_;
225 scoped_ptr<SSLSocketDataProvider> ssl_data_;
226 scoped_ptr<DeterministicSocketData> data_;
227 HttpProxyClientSocketPool pool_;
228 ClientSocketHandle handle_;
229 TestCompletionCallback callback_;
232 //-----------------------------------------------------------------------------
233 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
234 // and SPDY.
236 // TODO(akalin): Use ::testing::Combine() when we are able to use
237 // <tr1/tuple>.
238 INSTANTIATE_TEST_CASE_P(
239 HttpProxyClientSocketPoolTests,
240 HttpProxyClientSocketPoolTest,
241 ::testing::Values(
242 HttpProxyClientSocketPoolTestParams(HTTP, kProtoDeprecatedSPDY2),
243 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoDeprecatedSPDY2),
244 HttpProxyClientSocketPoolTestParams(SPDY, kProtoDeprecatedSPDY2),
245 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3),
246 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3),
247 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3),
248 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
249 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
250 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
251 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4),
252 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4),
253 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4)));
255 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
256 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
258 int rv = handle_.Init("a", CreateNoTunnelParams(), LOW, CompletionCallback(),
259 &pool_, BoundNetLog());
260 EXPECT_EQ(OK, rv);
261 EXPECT_TRUE(handle_.is_initialized());
262 ASSERT_TRUE(handle_.socket());
263 HttpProxyClientSocket* tunnel_socket =
264 static_cast<HttpProxyClientSocket*>(handle_.socket());
265 EXPECT_TRUE(tunnel_socket->IsConnected());
268 // Make sure that HttpProxyConnectJob passes on its priority to its
269 // (non-SSL) socket request on Init.
270 TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
271 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
272 EXPECT_EQ(OK,
273 handle_.Init("a", CreateNoTunnelParams(), HIGHEST,
274 CompletionCallback(), &pool_, BoundNetLog()));
275 EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
278 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
279 MockWrite writes[] = {
280 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
281 "Host: www.google.com\r\n"
282 "Proxy-Connection: keep-alive\r\n\r\n"),
284 MockRead reads[] = {
285 // No credentials.
286 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
287 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
288 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
289 MockRead(ASYNC, 4, "0123456789"),
291 scoped_ptr<SpdyFrame> req(
292 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOW));
293 scoped_ptr<SpdyFrame> rst(
294 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
295 MockWrite spdy_writes[] = {
296 CreateMockWrite(*req, 0, ASYNC),
297 CreateMockWrite(*rst, 2, ASYNC),
299 SpdyHeaderBlock resp_block;
300 resp_block[spdy_util_.GetStatusKey()] = "407";
301 resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
302 spdy_util_.MaybeAddVersionHeader(&resp_block);
304 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
305 MockRead spdy_reads[] = {
306 CreateMockRead(*resp, 1, ASYNC),
307 MockRead(ASYNC, 0, 3)
310 Initialize(reads, arraysize(reads), writes, arraysize(writes),
311 spdy_reads, arraysize(spdy_reads), spdy_writes,
312 arraysize(spdy_writes));
314 data_->StopAfter(4);
315 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
316 &pool_, BoundNetLog());
317 EXPECT_EQ(ERR_IO_PENDING, rv);
318 EXPECT_FALSE(handle_.is_initialized());
319 EXPECT_FALSE(handle_.socket());
321 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
322 rv = callback_.WaitForResult();
323 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
324 EXPECT_TRUE(handle_.is_initialized());
325 ASSERT_TRUE(handle_.socket());
326 ProxyClientSocket* tunnel_socket =
327 static_cast<ProxyClientSocket*>(handle_.socket());
328 if (GetParam().proxy_type == SPDY) {
329 EXPECT_TRUE(tunnel_socket->IsConnected());
330 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
331 } else {
332 EXPECT_FALSE(tunnel_socket->IsConnected());
333 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
337 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
338 // It's pretty much impossible to make the SPDY case behave synchronously
339 // so we skip this test for SPDY
340 if (GetParam().proxy_type == SPDY)
341 return;
342 MockWrite writes[] = {
343 MockWrite(SYNCHRONOUS, 0,
344 "CONNECT www.google.com:443 HTTP/1.1\r\n"
345 "Host: www.google.com\r\n"
346 "Proxy-Connection: keep-alive\r\n"
347 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
349 MockRead reads[] = {
350 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
353 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
354 NULL, 0);
355 AddAuthToCache();
357 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
358 &pool_, BoundNetLog());
359 EXPECT_EQ(OK, rv);
360 EXPECT_TRUE(handle_.is_initialized());
361 ASSERT_TRUE(handle_.socket());
362 HttpProxyClientSocket* tunnel_socket =
363 static_cast<HttpProxyClientSocket*>(handle_.socket());
364 EXPECT_TRUE(tunnel_socket->IsConnected());
367 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
368 MockWrite writes[] = {
369 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
370 "Host: www.google.com\r\n"
371 "Proxy-Connection: keep-alive\r\n"
372 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
374 MockRead reads[] = {
375 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
378 scoped_ptr<SpdyFrame> req(
379 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
380 MockWrite spdy_writes[] = {
381 CreateMockWrite(*req, 0, ASYNC)
383 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
384 MockRead spdy_reads[] = {
385 CreateMockRead(*resp, 1, ASYNC),
386 MockRead(ASYNC, 0, 2)
389 Initialize(reads, arraysize(reads), writes, arraysize(writes),
390 spdy_reads, arraysize(spdy_reads), spdy_writes,
391 arraysize(spdy_writes));
392 AddAuthToCache();
394 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
395 &pool_, BoundNetLog());
396 EXPECT_EQ(ERR_IO_PENDING, rv);
397 EXPECT_FALSE(handle_.is_initialized());
398 EXPECT_FALSE(handle_.socket());
400 data_->RunFor(2);
401 EXPECT_EQ(OK, callback_.WaitForResult());
402 EXPECT_TRUE(handle_.is_initialized());
403 ASSERT_TRUE(handle_.socket());
404 HttpProxyClientSocket* tunnel_socket =
405 static_cast<HttpProxyClientSocket*>(handle_.socket());
406 EXPECT_TRUE(tunnel_socket->IsConnected());
409 // Make sure that HttpProxyConnectJob passes on its priority to its
410 // SPDY session's socket request on Init (if applicable).
411 TEST_P(HttpProxyClientSocketPoolTest,
412 SetSpdySessionSocketRequestPriorityOnInit) {
413 if (GetParam().proxy_type != SPDY)
414 return;
416 scoped_ptr<SpdyFrame> req(
417 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize,
418 1, MEDIUM));
419 MockWrite spdy_writes[] = {
420 CreateMockWrite(*req, 0, ASYNC)
422 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
423 MockRead spdy_reads[] = {
424 CreateMockRead(*resp, 1, ASYNC),
425 MockRead(ASYNC, 0, 2)
428 Initialize(NULL, 0, NULL, 0,
429 spdy_reads, arraysize(spdy_reads),
430 spdy_writes, arraysize(spdy_writes));
431 AddAuthToCache();
433 EXPECT_EQ(ERR_IO_PENDING,
434 handle_.Init("a", CreateTunnelParams(), MEDIUM,
435 callback_.callback(), &pool_, BoundNetLog()));
436 EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
438 data_->RunFor(2);
439 EXPECT_EQ(OK, callback_.WaitForResult());
442 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
443 if (GetParam().proxy_type == SPDY) return;
444 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
445 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
447 socket_factory()->AddSocketDataProvider(data_.get());
449 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
450 &pool_, BoundNetLog());
451 EXPECT_EQ(ERR_IO_PENDING, rv);
452 EXPECT_FALSE(handle_.is_initialized());
453 EXPECT_FALSE(handle_.socket());
455 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
457 EXPECT_FALSE(handle_.is_initialized());
458 EXPECT_FALSE(handle_.socket());
461 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
462 if (GetParam().proxy_type == HTTP) return;
463 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
464 data_->set_connect_data(MockConnect(ASYNC, OK));
465 socket_factory()->AddSocketDataProvider(data_.get());
467 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
468 ERR_CERT_AUTHORITY_INVALID));
469 if (GetParam().proxy_type == SPDY) {
470 InitializeSpdySsl();
472 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
474 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
475 &pool_, BoundNetLog());
476 EXPECT_EQ(ERR_IO_PENDING, rv);
477 EXPECT_FALSE(handle_.is_initialized());
478 EXPECT_FALSE(handle_.socket());
480 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
482 EXPECT_FALSE(handle_.is_initialized());
483 EXPECT_FALSE(handle_.socket());
486 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
487 if (GetParam().proxy_type == HTTP) return;
488 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
489 data_->set_connect_data(MockConnect(ASYNC, OK));
490 socket_factory()->AddSocketDataProvider(data_.get());
492 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
493 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
494 if (GetParam().proxy_type == SPDY) {
495 InitializeSpdySsl();
497 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
499 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
500 &pool_, BoundNetLog());
501 EXPECT_EQ(ERR_IO_PENDING, rv);
502 EXPECT_FALSE(handle_.is_initialized());
503 EXPECT_FALSE(handle_.socket());
505 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
507 EXPECT_FALSE(handle_.is_initialized());
508 EXPECT_FALSE(handle_.socket());
511 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
512 MockWrite writes[] = {
513 MockWrite(ASYNC, 0,
514 "CONNECT www.google.com:443 HTTP/1.1\r\n"
515 "Host: www.google.com\r\n"
516 "Proxy-Connection: keep-alive\r\n"
517 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
519 MockRead reads[] = {
520 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
521 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
523 scoped_ptr<SpdyFrame> req(
524 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
525 MockWrite spdy_writes[] = {
526 CreateMockWrite(*req, 0, ASYNC)
528 MockRead spdy_reads[] = {
529 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
532 Initialize(reads, arraysize(reads), writes, arraysize(writes),
533 spdy_reads, arraysize(spdy_reads), spdy_writes,
534 arraysize(spdy_writes));
535 AddAuthToCache();
537 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
538 &pool_, BoundNetLog());
539 EXPECT_EQ(ERR_IO_PENDING, rv);
540 EXPECT_FALSE(handle_.is_initialized());
541 EXPECT_FALSE(handle_.socket());
543 data_->RunFor(3);
544 if (GetParam().proxy_type == SPDY) {
545 // SPDY cannot process a headers block unless it's complete and so it
546 // returns ERR_CONNECTION_CLOSED in this case.
547 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
548 } else {
549 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
551 EXPECT_FALSE(handle_.is_initialized());
552 EXPECT_FALSE(handle_.socket());
555 TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
556 // Tests that 1xx responses are rejected for a CONNECT request.
557 if (GetParam().proxy_type == SPDY) {
558 // SPDY doesn't have 1xx responses.
559 return;
562 MockWrite writes[] = {
563 MockWrite(ASYNC, 0,
564 "CONNECT www.google.com:443 HTTP/1.1\r\n"
565 "Host: www.google.com\r\n"
566 "Proxy-Connection: keep-alive\r\n\r\n"),
568 MockRead reads[] = {
569 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
570 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
573 Initialize(reads, arraysize(reads), writes, arraysize(writes),
574 NULL, 0, NULL, 0);
576 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
577 &pool_, BoundNetLog());
578 EXPECT_EQ(ERR_IO_PENDING, rv);
579 EXPECT_FALSE(handle_.is_initialized());
580 EXPECT_FALSE(handle_.socket());
582 data_->RunFor(2);
583 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
586 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
587 MockWrite writes[] = {
588 MockWrite(ASYNC, 0,
589 "CONNECT www.google.com:443 HTTP/1.1\r\n"
590 "Host: www.google.com\r\n"
591 "Proxy-Connection: keep-alive\r\n"
592 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
594 MockRead reads[] = {
595 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
597 scoped_ptr<SpdyFrame> req(
598 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
599 scoped_ptr<SpdyFrame> rst(
600 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
601 MockWrite spdy_writes[] = {
602 CreateMockWrite(*req, 0, ASYNC),
603 CreateMockWrite(*rst, 2, ASYNC),
605 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
606 MockRead spdy_reads[] = {
607 CreateMockRead(*resp, 1, ASYNC),
608 MockRead(ASYNC, 0, 3),
611 Initialize(reads, arraysize(reads), writes, arraysize(writes),
612 spdy_reads, arraysize(spdy_reads), spdy_writes,
613 arraysize(spdy_writes));
614 AddAuthToCache();
616 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
617 &pool_, BoundNetLog());
618 EXPECT_EQ(ERR_IO_PENDING, rv);
619 EXPECT_FALSE(handle_.is_initialized());
620 EXPECT_FALSE(handle_.socket());
622 data_->RunFor(2);
624 rv = callback_.WaitForResult();
625 // All Proxy CONNECT responses are not trustworthy
626 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
627 EXPECT_FALSE(handle_.is_initialized());
628 EXPECT_FALSE(handle_.socket());
631 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
632 const std::string redirectTarget = "https://foo.google.com/";
634 const std::string responseText = "HTTP/1.1 302 Found\r\n"
635 "Location: " + redirectTarget + "\r\n"
636 "Set-Cookie: foo=bar\r\n"
637 "\r\n";
638 MockWrite writes[] = {
639 MockWrite(ASYNC, 0,
640 "CONNECT www.google.com:443 HTTP/1.1\r\n"
641 "Host: www.google.com\r\n"
642 "Proxy-Connection: keep-alive\r\n"
643 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
645 MockRead reads[] = {
646 MockRead(ASYNC, 1, responseText.c_str()),
648 scoped_ptr<SpdyFrame> req(
649 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
650 scoped_ptr<SpdyFrame> rst(
651 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
653 MockWrite spdy_writes[] = {
654 CreateMockWrite(*req, 0, ASYNC),
655 CreateMockWrite(*rst, 3, ASYNC),
658 const char* const responseHeaders[] = {
659 "location", redirectTarget.c_str(),
660 "set-cookie", "foo=bar",
662 const int responseHeadersSize = arraysize(responseHeaders) / 2;
663 scoped_ptr<SpdyFrame> resp(
664 spdy_util_.ConstructSpdySynReplyError(
665 "302 Found",
666 responseHeaders, responseHeadersSize,
667 1));
668 MockRead spdy_reads[] = {
669 CreateMockRead(*resp, 1, ASYNC),
670 MockRead(ASYNC, 0, 2),
673 Initialize(reads, arraysize(reads), writes, arraysize(writes),
674 spdy_reads, arraysize(spdy_reads), spdy_writes,
675 arraysize(spdy_writes));
676 AddAuthToCache();
678 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
679 &pool_, BoundNetLog());
680 EXPECT_EQ(ERR_IO_PENDING, rv);
681 EXPECT_FALSE(handle_.is_initialized());
682 EXPECT_FALSE(handle_.socket());
684 data_->RunFor(2);
686 rv = callback_.WaitForResult();
688 if (GetParam().proxy_type == HTTP) {
689 // We don't trust 302 responses to CONNECT from HTTP proxies.
690 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
691 EXPECT_FALSE(handle_.is_initialized());
692 EXPECT_FALSE(handle_.socket());
693 } else {
694 // Expect ProxyClientSocket to return the proxy's response, sanitized.
695 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
696 EXPECT_TRUE(handle_.is_initialized());
697 ASSERT_TRUE(handle_.socket());
699 const ProxyClientSocket* tunnel_socket =
700 static_cast<ProxyClientSocket*>(handle_.socket());
701 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
702 const HttpResponseHeaders* headers = response->headers.get();
704 // Make sure Set-Cookie header was stripped.
705 EXPECT_FALSE(headers->HasHeader("set-cookie"));
707 // Make sure Content-Length: 0 header was added.
708 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
710 // Make sure Location header was included and correct.
711 std::string location;
712 EXPECT_TRUE(headers->IsRedirect(&location));
713 EXPECT_EQ(location, redirectTarget);
717 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
719 } // namespace
721 } // namespace net