Update include paths in miscellaneous content/ directories for base/process changes.
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blobacd60a6afe0501cce26f0fc10b9ffd25489d28fd
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(kProtoSPDY2) {}
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 } // namespace
60 class HttpProxyClientSocketPoolTest
61 : public ::testing::TestWithParam<HttpProxyClientSocketPoolTestParams> {
62 protected:
63 HttpProxyClientSocketPoolTest()
64 : session_deps_(GetParam().protocol),
65 ssl_config_(),
66 ignored_transport_socket_params_(
67 new TransportSocketParams(HostPortPair("proxy", 80),
68 LOWEST,
69 false,
70 false,
71 OnHostResolutionCallback())),
72 ignored_ssl_socket_params_(
73 new SSLSocketParams(ignored_transport_socket_params_,
74 NULL,
75 NULL,
76 ProxyServer::SCHEME_DIRECT,
77 HostPortPair("www.google.com", 443),
78 ssl_config_,
79 kPrivacyModeDisabled,
81 false,
82 false)),
83 tcp_histograms_("MockTCP"),
84 transport_socket_pool_(
85 kMaxSockets,
86 kMaxSocketsPerGroup,
87 &tcp_histograms_,
88 session_deps_.deterministic_socket_factory.get()),
89 ssl_histograms_("MockSSL"),
90 ssl_socket_pool_(kMaxSockets,
91 kMaxSocketsPerGroup,
92 &ssl_histograms_,
93 session_deps_.host_resolver.get(),
94 session_deps_.cert_verifier.get(),
95 NULL /* server_bound_cert_store */,
96 NULL /* transport_security_state */,
97 std::string() /* ssl_session_cache_shard */,
98 session_deps_.deterministic_socket_factory.get(),
99 &transport_socket_pool_,
100 NULL,
101 NULL,
102 session_deps_.ssl_config_service.get(),
103 BoundNetLog().net_log()),
104 session_(CreateNetworkSession()),
105 http_proxy_histograms_("HttpProxyUnitTest"),
106 spdy_util_(GetParam().protocol),
107 pool_(kMaxSockets,
108 kMaxSocketsPerGroup,
109 &http_proxy_histograms_,
110 NULL,
111 &transport_socket_pool_,
112 &ssl_socket_pool_,
113 NULL) {}
115 virtual ~HttpProxyClientSocketPoolTest() {
118 void AddAuthToCache() {
119 const base::string16 kFoo(ASCIIToUTF16("foo"));
120 const base::string16 kBar(ASCIIToUTF16("bar"));
121 GURL proxy_url(GetParam().proxy_type == HTTP ? "http://proxy" : "https://proxy:80");
122 session_->http_auth_cache()->Add(proxy_url,
123 "MyRealm1",
124 HttpAuth::AUTH_SCHEME_BASIC,
125 "Basic realm=MyRealm1",
126 AuthCredentials(kFoo, kBar),
127 "/");
130 scoped_refptr<TransportSocketParams> GetTcpParams() {
131 if (GetParam().proxy_type != HTTP)
132 return scoped_refptr<TransportSocketParams>();
133 return ignored_transport_socket_params_;
136 scoped_refptr<SSLSocketParams> GetSslParams() {
137 if (GetParam().proxy_type == HTTP)
138 return scoped_refptr<SSLSocketParams>();
139 return ignored_ssl_socket_params_;
142 // Returns the a correctly constructed HttpProxyParms
143 // for the HTTP or HTTPS proxy.
144 scoped_refptr<HttpProxySocketParams> GetParams(bool tunnel) {
145 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
146 GetTcpParams(),
147 GetSslParams(),
148 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
149 std::string(),
150 HostPortPair("www.google.com", tunnel ? 443 : 80),
151 session_->http_auth_cache(),
152 session_->http_auth_handler_factory(),
153 session_->spdy_session_pool(),
154 tunnel));
157 scoped_refptr<HttpProxySocketParams> GetTunnelParams() {
158 return GetParams(true);
161 scoped_refptr<HttpProxySocketParams> GetNoTunnelParams() {
162 return GetParams(false);
165 DeterministicMockClientSocketFactory& socket_factory() {
166 return *session_deps_.deterministic_socket_factory.get();
169 void Initialize(MockRead* reads, size_t reads_count,
170 MockWrite* writes, size_t writes_count,
171 MockRead* spdy_reads, size_t spdy_reads_count,
172 MockWrite* spdy_writes, size_t spdy_writes_count) {
173 if (GetParam().proxy_type == SPDY) {
174 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
175 spdy_writes, spdy_writes_count));
176 } else {
177 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
178 writes_count));
181 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
182 data_->StopAfter(2); // Request / Response
184 socket_factory().AddSocketDataProvider(data_.get());
186 if (GetParam().proxy_type != HTTP) {
187 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
188 if (GetParam().proxy_type == SPDY) {
189 InitializeSpdySsl();
191 socket_factory().AddSSLSocketDataProvider(ssl_data_.get());
195 void InitializeSpdySsl() {
196 ssl_data_->SetNextProto(GetParam().protocol);
199 HttpNetworkSession* CreateNetworkSession() {
200 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
201 &session_deps_);
204 private:
205 SpdySessionDependencies session_deps_;
206 SSLConfig ssl_config_;
208 scoped_refptr<TransportSocketParams> ignored_transport_socket_params_;
209 scoped_refptr<SSLSocketParams> ignored_ssl_socket_params_;
210 ClientSocketPoolHistograms tcp_histograms_;
211 MockTransportClientSocketPool transport_socket_pool_;
212 ClientSocketPoolHistograms ssl_histograms_;
213 MockHostResolver host_resolver_;
214 scoped_ptr<CertVerifier> cert_verifier_;
215 SSLClientSocketPool ssl_socket_pool_;
217 const scoped_refptr<HttpNetworkSession> session_;
218 ClientSocketPoolHistograms http_proxy_histograms_;
220 protected:
221 SpdyTestUtil spdy_util_;
222 scoped_ptr<SSLSocketDataProvider> ssl_data_;
223 scoped_ptr<DeterministicSocketData> data_;
224 HttpProxyClientSocketPool pool_;
225 ClientSocketHandle handle_;
226 TestCompletionCallback callback_;
229 //-----------------------------------------------------------------------------
230 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
231 // and SPDY.
233 // TODO(akalin): Use ::testing::Combine() when we are able to use
234 // <tr1/tuple>.
235 INSTANTIATE_TEST_CASE_P(
236 HttpProxyClientSocketPoolTests,
237 HttpProxyClientSocketPoolTest,
238 ::testing::Values(
239 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY2),
240 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY2),
241 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY2),
242 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3),
243 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3),
244 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3),
245 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
246 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
247 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
248 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4a2),
249 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4a2),
250 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4a2)));
252 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
253 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
255 int rv = handle_.Init("a", GetNoTunnelParams(), LOW, CompletionCallback(),
256 &pool_, BoundNetLog());
257 EXPECT_EQ(OK, rv);
258 EXPECT_TRUE(handle_.is_initialized());
259 ASSERT_TRUE(handle_.socket());
260 HttpProxyClientSocket* tunnel_socket =
261 static_cast<HttpProxyClientSocket*>(handle_.socket());
262 EXPECT_TRUE(tunnel_socket->IsConnected());
265 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
266 MockWrite writes[] = {
267 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
268 "Host: www.google.com\r\n"
269 "Proxy-Connection: keep-alive\r\n\r\n"),
271 MockRead reads[] = {
272 // No credentials.
273 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
274 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
275 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
276 MockRead(ASYNC, 4, "0123456789"),
278 scoped_ptr<SpdyFrame> req(
279 spdy_util_.ConstructSpdyConnect(NULL, 0, 1));
280 scoped_ptr<SpdyFrame> rst(
281 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
282 MockWrite spdy_writes[] = {
283 CreateMockWrite(*req, 0, ASYNC),
284 CreateMockWrite(*rst, 2, ASYNC),
286 const char* const kAuthChallenge[] = {
287 spdy_util_.GetStatusKey(), "407 Proxy Authentication Required",
288 spdy_util_.GetVersionKey(), "HTTP/1.1",
289 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
291 scoped_ptr<SpdyFrame> resp(
292 spdy_util_.ConstructSpdyControlFrame(NULL,
294 false,
296 LOWEST,
297 SYN_REPLY,
298 CONTROL_FLAG_NONE,
299 kAuthChallenge,
300 arraysize(kAuthChallenge),
301 0));
302 MockRead spdy_reads[] = {
303 CreateMockRead(*resp, 1, ASYNC),
304 MockRead(ASYNC, 0, 3)
307 Initialize(reads, arraysize(reads), writes, arraysize(writes),
308 spdy_reads, arraysize(spdy_reads), spdy_writes,
309 arraysize(spdy_writes));
311 data_->StopAfter(4);
312 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
313 &pool_, BoundNetLog());
314 EXPECT_EQ(ERR_IO_PENDING, rv);
315 EXPECT_FALSE(handle_.is_initialized());
316 EXPECT_FALSE(handle_.socket());
318 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
319 rv = callback_.WaitForResult();
320 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
321 EXPECT_TRUE(handle_.is_initialized());
322 ASSERT_TRUE(handle_.socket());
323 ProxyClientSocket* tunnel_socket =
324 static_cast<ProxyClientSocket*>(handle_.socket());
325 if (GetParam().proxy_type == SPDY) {
326 EXPECT_TRUE(tunnel_socket->IsConnected());
327 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
328 } else {
329 EXPECT_FALSE(tunnel_socket->IsConnected());
330 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
331 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
335 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
336 // It's pretty much impossible to make the SPDY case behave synchronously
337 // so we skip this test for SPDY
338 if (GetParam().proxy_type == SPDY)
339 return;
340 MockWrite writes[] = {
341 MockWrite(SYNCHRONOUS, 0,
342 "CONNECT www.google.com:443 HTTP/1.1\r\n"
343 "Host: www.google.com\r\n"
344 "Proxy-Connection: keep-alive\r\n"
345 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
347 MockRead reads[] = {
348 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
351 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
352 NULL, 0);
353 AddAuthToCache();
355 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
356 &pool_, BoundNetLog());
357 EXPECT_EQ(OK, rv);
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());
365 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
366 MockWrite writes[] = {
367 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
368 "Host: www.google.com\r\n"
369 "Proxy-Connection: keep-alive\r\n"
370 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
372 MockRead reads[] = {
373 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
376 scoped_ptr<SpdyFrame> req(
377 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1));
378 MockWrite spdy_writes[] = {
379 CreateMockWrite(*req, 0, ASYNC)
381 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
382 MockRead spdy_reads[] = {
383 CreateMockRead(*resp, 1, ASYNC),
384 MockRead(ASYNC, 0, 2)
387 Initialize(reads, arraysize(reads), writes, arraysize(writes),
388 spdy_reads, arraysize(spdy_reads), spdy_writes,
389 arraysize(spdy_writes));
390 AddAuthToCache();
392 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
393 &pool_, BoundNetLog());
394 EXPECT_EQ(ERR_IO_PENDING, rv);
395 EXPECT_FALSE(handle_.is_initialized());
396 EXPECT_FALSE(handle_.socket());
398 data_->RunFor(2);
399 EXPECT_EQ(OK, callback_.WaitForResult());
400 EXPECT_TRUE(handle_.is_initialized());
401 ASSERT_TRUE(handle_.socket());
402 HttpProxyClientSocket* tunnel_socket =
403 static_cast<HttpProxyClientSocket*>(handle_.socket());
404 EXPECT_TRUE(tunnel_socket->IsConnected());
407 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
408 if (GetParam().proxy_type == SPDY) return;
409 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
410 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
412 socket_factory().AddSocketDataProvider(data_.get());
414 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
415 &pool_, BoundNetLog());
416 EXPECT_EQ(ERR_IO_PENDING, rv);
417 EXPECT_FALSE(handle_.is_initialized());
418 EXPECT_FALSE(handle_.socket());
420 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
422 EXPECT_FALSE(handle_.is_initialized());
423 EXPECT_FALSE(handle_.socket());
426 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
427 if (GetParam().proxy_type == HTTP) return;
428 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
429 data_->set_connect_data(MockConnect(ASYNC, OK));
430 socket_factory().AddSocketDataProvider(data_.get());
432 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
433 ERR_CERT_AUTHORITY_INVALID));
434 if (GetParam().proxy_type == SPDY) {
435 InitializeSpdySsl();
437 socket_factory().AddSSLSocketDataProvider(ssl_data_.get());
439 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
440 &pool_, BoundNetLog());
441 EXPECT_EQ(ERR_IO_PENDING, rv);
442 EXPECT_FALSE(handle_.is_initialized());
443 EXPECT_FALSE(handle_.socket());
445 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
447 EXPECT_FALSE(handle_.is_initialized());
448 EXPECT_FALSE(handle_.socket());
451 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
452 if (GetParam().proxy_type == HTTP) return;
453 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
454 data_->set_connect_data(MockConnect(ASYNC, OK));
455 socket_factory().AddSocketDataProvider(data_.get());
457 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
458 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
459 if (GetParam().proxy_type == SPDY) {
460 InitializeSpdySsl();
462 socket_factory().AddSSLSocketDataProvider(ssl_data_.get());
464 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
465 &pool_, BoundNetLog());
466 EXPECT_EQ(ERR_IO_PENDING, rv);
467 EXPECT_FALSE(handle_.is_initialized());
468 EXPECT_FALSE(handle_.socket());
470 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
472 EXPECT_FALSE(handle_.is_initialized());
473 EXPECT_FALSE(handle_.socket());
476 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
477 MockWrite writes[] = {
478 MockWrite(ASYNC, 0,
479 "CONNECT www.google.com:443 HTTP/1.1\r\n"
480 "Host: www.google.com\r\n"
481 "Proxy-Connection: keep-alive\r\n"
482 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
484 MockRead reads[] = {
485 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
486 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
488 scoped_ptr<SpdyFrame> req(
489 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1));
490 MockWrite spdy_writes[] = {
491 CreateMockWrite(*req, 0, ASYNC)
493 MockRead spdy_reads[] = {
494 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
497 Initialize(reads, arraysize(reads), writes, arraysize(writes),
498 spdy_reads, arraysize(spdy_reads), spdy_writes,
499 arraysize(spdy_writes));
500 AddAuthToCache();
502 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
503 &pool_, BoundNetLog());
504 EXPECT_EQ(ERR_IO_PENDING, rv);
505 EXPECT_FALSE(handle_.is_initialized());
506 EXPECT_FALSE(handle_.socket());
508 data_->RunFor(3);
509 if (GetParam().proxy_type == SPDY) {
510 // SPDY cannot process a headers block unless it's complete and so it
511 // returns ERR_CONNECTION_CLOSED in this case.
512 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
513 } else {
514 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
516 EXPECT_FALSE(handle_.is_initialized());
517 EXPECT_FALSE(handle_.socket());
520 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
521 MockWrite writes[] = {
522 MockWrite(ASYNC, 0,
523 "CONNECT www.google.com:443 HTTP/1.1\r\n"
524 "Host: www.google.com\r\n"
525 "Proxy-Connection: keep-alive\r\n"
526 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
528 MockRead reads[] = {
529 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
531 scoped_ptr<SpdyFrame> req(
532 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1));
533 scoped_ptr<SpdyFrame> rst(
534 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
535 MockWrite spdy_writes[] = {
536 CreateMockWrite(*req, 0, ASYNC),
537 CreateMockWrite(*rst, 2, ASYNC),
539 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
540 MockRead spdy_reads[] = {
541 CreateMockRead(*resp, 1, ASYNC),
542 MockRead(ASYNC, 0, 3),
545 Initialize(reads, arraysize(reads), writes, arraysize(writes),
546 spdy_reads, arraysize(spdy_reads), spdy_writes,
547 arraysize(spdy_writes));
548 AddAuthToCache();
550 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
551 &pool_, BoundNetLog());
552 EXPECT_EQ(ERR_IO_PENDING, rv);
553 EXPECT_FALSE(handle_.is_initialized());
554 EXPECT_FALSE(handle_.socket());
556 data_->RunFor(2);
558 rv = callback_.WaitForResult();
559 // All Proxy CONNECT responses are not trustworthy
560 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
561 EXPECT_FALSE(handle_.is_initialized());
562 EXPECT_FALSE(handle_.socket());
565 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
566 const std::string redirectTarget = "https://foo.google.com/";
568 const std::string responseText = "HTTP/1.1 302 Found\r\n"
569 "Location: " + redirectTarget + "\r\n"
570 "Set-Cookie: foo=bar\r\n"
571 "\r\n";
572 MockWrite writes[] = {
573 MockWrite(ASYNC, 0,
574 "CONNECT www.google.com:443 HTTP/1.1\r\n"
575 "Host: www.google.com\r\n"
576 "Proxy-Connection: keep-alive\r\n"
577 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
579 MockRead reads[] = {
580 MockRead(ASYNC, 1, responseText.c_str()),
582 scoped_ptr<SpdyFrame> req(
583 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1));
584 scoped_ptr<SpdyFrame> rst(
585 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
587 MockWrite spdy_writes[] = {
588 CreateMockWrite(*req, 0, ASYNC),
589 CreateMockWrite(*rst, 3, ASYNC),
592 const char* const responseHeaders[] = {
593 "location", redirectTarget.c_str(),
594 "set-cookie", "foo=bar",
596 const int responseHeadersSize = arraysize(responseHeaders) / 2;
597 scoped_ptr<SpdyFrame> resp(
598 spdy_util_.ConstructSpdySynReplyError(
599 "302 Found",
600 responseHeaders, responseHeadersSize,
601 1));
602 MockRead spdy_reads[] = {
603 CreateMockRead(*resp, 1, ASYNC),
604 MockRead(ASYNC, 0, 2),
607 Initialize(reads, arraysize(reads), writes, arraysize(writes),
608 spdy_reads, arraysize(spdy_reads), spdy_writes,
609 arraysize(spdy_writes));
610 AddAuthToCache();
612 int rv = handle_.Init("a", GetTunnelParams(), LOW, callback_.callback(),
613 &pool_, BoundNetLog());
614 EXPECT_EQ(ERR_IO_PENDING, rv);
615 EXPECT_FALSE(handle_.is_initialized());
616 EXPECT_FALSE(handle_.socket());
618 data_->RunFor(2);
620 rv = callback_.WaitForResult();
622 if (GetParam().proxy_type == HTTP) {
623 // We don't trust 302 responses to CONNECT from HTTP proxies.
624 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
625 EXPECT_FALSE(handle_.is_initialized());
626 EXPECT_FALSE(handle_.socket());
627 } else {
628 // Expect ProxyClientSocket to return the proxy's response, sanitized.
629 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
630 EXPECT_TRUE(handle_.is_initialized());
631 ASSERT_TRUE(handle_.socket());
633 const ProxyClientSocket* tunnel_socket =
634 static_cast<ProxyClientSocket*>(handle_.socket());
635 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
636 const HttpResponseHeaders* headers = response->headers.get();
638 // Make sure Set-Cookie header was stripped.
639 EXPECT_FALSE(headers->HasHeader("set-cookie"));
641 // Make sure Content-Length: 0 header was added.
642 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
644 // Make sure Location header was included and correct.
645 std::string location;
646 EXPECT_TRUE(headers->IsRedirect(&location));
647 EXPECT_EQ(location, redirectTarget);
651 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
653 } // namespace net