Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / net / http / http_proxy_client_socket_pool_unittest.cc
blobf2464919e3a72e53a9a3c66a76db1490d50b98f5
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 /* channel_id_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 false,
88 BoundNetLog().net_log()),
89 session_(CreateNetworkSession()),
90 http_proxy_histograms_("HttpProxyUnitTest"),
91 spdy_util_(GetParam().protocol),
92 pool_(kMaxSockets,
93 kMaxSocketsPerGroup,
94 &http_proxy_histograms_,
95 NULL,
96 &transport_socket_pool_,
97 &ssl_socket_pool_,
98 NULL) {}
100 virtual ~HttpProxyClientSocketPoolTest() {
103 void AddAuthToCache() {
104 const base::string16 kFoo(base::ASCIIToUTF16("foo"));
105 const base::string16 kBar(base::ASCIIToUTF16("bar"));
106 GURL proxy_url(GetParam().proxy_type == HTTP ?
107 (std::string("http://") + kHttpProxyHost) :
108 (std::string("https://") + kHttpsProxyHost));
109 session_->http_auth_cache()->Add(proxy_url,
110 "MyRealm1",
111 HttpAuth::AUTH_SCHEME_BASIC,
112 "Basic realm=MyRealm1",
113 AuthCredentials(kFoo, kBar),
114 "/");
117 scoped_refptr<TransportSocketParams> CreateHttpProxyParams() const {
118 if (GetParam().proxy_type != HTTP)
119 return NULL;
120 return new TransportSocketParams(HostPortPair(kHttpProxyHost, 80),
121 false,
122 false,
123 OnHostResolutionCallback());
126 scoped_refptr<SSLSocketParams> CreateHttpsProxyParams() const {
127 if (GetParam().proxy_type == HTTP)
128 return NULL;
129 return new SSLSocketParams(
130 new TransportSocketParams(
131 HostPortPair(kHttpsProxyHost, 443),
132 false,
133 false,
134 OnHostResolutionCallback()),
135 NULL,
136 NULL,
137 HostPortPair(kHttpsProxyHost, 443),
138 SSLConfig(),
139 PRIVACY_MODE_DISABLED,
141 false,
142 false);
145 // Returns the a correctly constructed HttpProxyParms
146 // for the HTTP or HTTPS proxy.
147 scoped_refptr<HttpProxySocketParams> CreateParams(bool tunnel) {
148 return scoped_refptr<HttpProxySocketParams>(new HttpProxySocketParams(
149 CreateHttpProxyParams(),
150 CreateHttpsProxyParams(),
151 GURL(tunnel ? "https://www.google.com/" : "http://www.google.com"),
152 std::string(),
153 HostPortPair("www.google.com", tunnel ? 443 : 80),
154 session_->http_auth_cache(),
155 session_->http_auth_handler_factory(),
156 session_->spdy_session_pool(),
157 tunnel));
160 scoped_refptr<HttpProxySocketParams> CreateTunnelParams() {
161 return CreateParams(true);
164 scoped_refptr<HttpProxySocketParams> CreateNoTunnelParams() {
165 return CreateParams(false);
168 DeterministicMockClientSocketFactory* socket_factory() {
169 return session_deps_.deterministic_socket_factory.get();
172 void Initialize(MockRead* reads, size_t reads_count,
173 MockWrite* writes, size_t writes_count,
174 MockRead* spdy_reads, size_t spdy_reads_count,
175 MockWrite* spdy_writes, size_t spdy_writes_count) {
176 if (GetParam().proxy_type == SPDY) {
177 data_.reset(new DeterministicSocketData(spdy_reads, spdy_reads_count,
178 spdy_writes, spdy_writes_count));
179 } else {
180 data_.reset(new DeterministicSocketData(reads, reads_count, writes,
181 writes_count));
184 data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
185 data_->StopAfter(2); // Request / Response
187 socket_factory()->AddSocketDataProvider(data_.get());
189 if (GetParam().proxy_type != HTTP) {
190 ssl_data_.reset(new SSLSocketDataProvider(SYNCHRONOUS, OK));
191 if (GetParam().proxy_type == SPDY) {
192 InitializeSpdySsl();
194 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
198 void InitializeSpdySsl() {
199 ssl_data_->SetNextProto(GetParam().protocol);
202 HttpNetworkSession* CreateNetworkSession() {
203 return SpdySessionDependencies::SpdyCreateSessionDeterministic(
204 &session_deps_);
207 RequestPriority GetLastTransportRequestPriority() const {
208 return transport_socket_pool_.last_request_priority();
211 private:
212 SpdySessionDependencies session_deps_;
214 ClientSocketPoolHistograms tcp_histograms_;
215 MockTransportClientSocketPool transport_socket_pool_;
216 ClientSocketPoolHistograms ssl_histograms_;
217 MockHostResolver host_resolver_;
218 scoped_ptr<CertVerifier> cert_verifier_;
219 SSLClientSocketPool ssl_socket_pool_;
221 const scoped_refptr<HttpNetworkSession> session_;
222 ClientSocketPoolHistograms http_proxy_histograms_;
224 protected:
225 SpdyTestUtil spdy_util_;
226 scoped_ptr<SSLSocketDataProvider> ssl_data_;
227 scoped_ptr<DeterministicSocketData> data_;
228 HttpProxyClientSocketPool pool_;
229 ClientSocketHandle handle_;
230 TestCompletionCallback callback_;
233 //-----------------------------------------------------------------------------
234 // All tests are run with three different proxy types: HTTP, HTTPS (non-SPDY)
235 // and SPDY.
237 // TODO(akalin): Use ::testing::Combine() when we are able to use
238 // <tr1/tuple>.
239 INSTANTIATE_TEST_CASE_P(
240 HttpProxyClientSocketPoolTests,
241 HttpProxyClientSocketPoolTest,
242 ::testing::Values(
243 HttpProxyClientSocketPoolTestParams(HTTP, kProtoDeprecatedSPDY2),
244 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoDeprecatedSPDY2),
245 HttpProxyClientSocketPoolTestParams(SPDY, kProtoDeprecatedSPDY2),
246 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3),
247 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3),
248 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3),
249 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31),
250 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31),
251 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31),
252 HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY4),
253 HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY4),
254 HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY4)));
256 TEST_P(HttpProxyClientSocketPoolTest, NoTunnel) {
257 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
259 int rv = handle_.Init("a", CreateNoTunnelParams(), LOW, CompletionCallback(),
260 &pool_, BoundNetLog());
261 EXPECT_EQ(OK, rv);
262 EXPECT_TRUE(handle_.is_initialized());
263 ASSERT_TRUE(handle_.socket());
264 HttpProxyClientSocket* tunnel_socket =
265 static_cast<HttpProxyClientSocket*>(handle_.socket());
266 EXPECT_TRUE(tunnel_socket->IsConnected());
269 // Make sure that HttpProxyConnectJob passes on its priority to its
270 // (non-SSL) socket request on Init.
271 TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
272 Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0);
273 EXPECT_EQ(OK,
274 handle_.Init("a", CreateNoTunnelParams(), HIGHEST,
275 CompletionCallback(), &pool_, BoundNetLog()));
276 EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority());
279 TEST_P(HttpProxyClientSocketPoolTest, NeedAuth) {
280 MockWrite writes[] = {
281 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
282 "Host: www.google.com\r\n"
283 "Proxy-Connection: keep-alive\r\n\r\n"),
285 MockRead reads[] = {
286 // No credentials.
287 MockRead(ASYNC, 1, "HTTP/1.1 407 Proxy Authentication Required\r\n"),
288 MockRead(ASYNC, 2, "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
289 MockRead(ASYNC, 3, "Content-Length: 10\r\n\r\n"),
290 MockRead(ASYNC, 4, "0123456789"),
292 scoped_ptr<SpdyFrame> req(
293 spdy_util_.ConstructSpdyConnect(NULL, 0, 1, LOW));
294 scoped_ptr<SpdyFrame> rst(
295 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
296 MockWrite spdy_writes[] = {
297 CreateMockWrite(*req, 0, ASYNC),
298 CreateMockWrite(*rst, 2, ASYNC),
300 SpdyHeaderBlock resp_block;
301 resp_block[spdy_util_.GetStatusKey()] = "407";
302 resp_block["proxy-authenticate"] = "Basic realm=\"MyRealm1\"";
303 spdy_util_.MaybeAddVersionHeader(&resp_block);
305 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyReply(1, resp_block));
306 MockRead spdy_reads[] = {
307 CreateMockRead(*resp, 1, ASYNC),
308 MockRead(ASYNC, 0, 3)
311 Initialize(reads, arraysize(reads), writes, arraysize(writes),
312 spdy_reads, arraysize(spdy_reads), spdy_writes,
313 arraysize(spdy_writes));
315 data_->StopAfter(4);
316 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
317 &pool_, BoundNetLog());
318 EXPECT_EQ(ERR_IO_PENDING, rv);
319 EXPECT_FALSE(handle_.is_initialized());
320 EXPECT_FALSE(handle_.socket());
322 data_->RunFor(GetParam().proxy_type == SPDY ? 2 : 4);
323 rv = callback_.WaitForResult();
324 EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, rv);
325 EXPECT_TRUE(handle_.is_initialized());
326 ASSERT_TRUE(handle_.socket());
327 ProxyClientSocket* tunnel_socket =
328 static_cast<ProxyClientSocket*>(handle_.socket());
329 if (GetParam().proxy_type == SPDY) {
330 EXPECT_TRUE(tunnel_socket->IsConnected());
331 EXPECT_TRUE(tunnel_socket->IsUsingSpdy());
332 } else {
333 EXPECT_FALSE(tunnel_socket->IsConnected());
334 EXPECT_FALSE(tunnel_socket->IsUsingSpdy());
338 TEST_P(HttpProxyClientSocketPoolTest, HaveAuth) {
339 // It's pretty much impossible to make the SPDY case behave synchronously
340 // so we skip this test for SPDY
341 if (GetParam().proxy_type == SPDY)
342 return;
343 MockWrite writes[] = {
344 MockWrite(SYNCHRONOUS, 0,
345 "CONNECT www.google.com:443 HTTP/1.1\r\n"
346 "Host: www.google.com\r\n"
347 "Proxy-Connection: keep-alive\r\n"
348 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
350 MockRead reads[] = {
351 MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
354 Initialize(reads, arraysize(reads), writes, arraysize(writes), NULL, 0,
355 NULL, 0);
356 AddAuthToCache();
358 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
359 &pool_, BoundNetLog());
360 EXPECT_EQ(OK, rv);
361 EXPECT_TRUE(handle_.is_initialized());
362 ASSERT_TRUE(handle_.socket());
363 HttpProxyClientSocket* tunnel_socket =
364 static_cast<HttpProxyClientSocket*>(handle_.socket());
365 EXPECT_TRUE(tunnel_socket->IsConnected());
368 TEST_P(HttpProxyClientSocketPoolTest, AsyncHaveAuth) {
369 MockWrite writes[] = {
370 MockWrite(ASYNC, 0, "CONNECT www.google.com:443 HTTP/1.1\r\n"
371 "Host: www.google.com\r\n"
372 "Proxy-Connection: keep-alive\r\n"
373 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
375 MockRead reads[] = {
376 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
379 scoped_ptr<SpdyFrame> req(
380 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
381 MockWrite spdy_writes[] = {
382 CreateMockWrite(*req, 0, ASYNC)
384 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
385 MockRead spdy_reads[] = {
386 CreateMockRead(*resp, 1, ASYNC),
387 MockRead(ASYNC, 0, 2)
390 Initialize(reads, arraysize(reads), writes, arraysize(writes),
391 spdy_reads, arraysize(spdy_reads), spdy_writes,
392 arraysize(spdy_writes));
393 AddAuthToCache();
395 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
396 &pool_, BoundNetLog());
397 EXPECT_EQ(ERR_IO_PENDING, rv);
398 EXPECT_FALSE(handle_.is_initialized());
399 EXPECT_FALSE(handle_.socket());
401 data_->RunFor(2);
402 EXPECT_EQ(OK, callback_.WaitForResult());
403 EXPECT_TRUE(handle_.is_initialized());
404 ASSERT_TRUE(handle_.socket());
405 HttpProxyClientSocket* tunnel_socket =
406 static_cast<HttpProxyClientSocket*>(handle_.socket());
407 EXPECT_TRUE(tunnel_socket->IsConnected());
410 // Make sure that HttpProxyConnectJob passes on its priority to its
411 // SPDY session's socket request on Init (if applicable).
412 TEST_P(HttpProxyClientSocketPoolTest,
413 SetSpdySessionSocketRequestPriorityOnInit) {
414 if (GetParam().proxy_type != SPDY)
415 return;
417 scoped_ptr<SpdyFrame> req(
418 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize,
419 1, MEDIUM));
420 MockWrite spdy_writes[] = {
421 CreateMockWrite(*req, 0, ASYNC)
423 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
424 MockRead spdy_reads[] = {
425 CreateMockRead(*resp, 1, ASYNC),
426 MockRead(ASYNC, 0, 2)
429 Initialize(NULL, 0, NULL, 0,
430 spdy_reads, arraysize(spdy_reads),
431 spdy_writes, arraysize(spdy_writes));
432 AddAuthToCache();
434 EXPECT_EQ(ERR_IO_PENDING,
435 handle_.Init("a", CreateTunnelParams(), MEDIUM,
436 callback_.callback(), &pool_, BoundNetLog()));
437 EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority());
439 data_->RunFor(2);
440 EXPECT_EQ(OK, callback_.WaitForResult());
443 TEST_P(HttpProxyClientSocketPoolTest, TCPError) {
444 if (GetParam().proxy_type == SPDY) return;
445 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
446 data_->set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_CLOSED));
448 socket_factory()->AddSocketDataProvider(data_.get());
450 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
451 &pool_, BoundNetLog());
452 EXPECT_EQ(ERR_IO_PENDING, rv);
453 EXPECT_FALSE(handle_.is_initialized());
454 EXPECT_FALSE(handle_.socket());
456 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, callback_.WaitForResult());
458 EXPECT_FALSE(handle_.is_initialized());
459 EXPECT_FALSE(handle_.socket());
462 TEST_P(HttpProxyClientSocketPoolTest, SSLError) {
463 if (GetParam().proxy_type == HTTP) return;
464 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
465 data_->set_connect_data(MockConnect(ASYNC, OK));
466 socket_factory()->AddSocketDataProvider(data_.get());
468 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
469 ERR_CERT_AUTHORITY_INVALID));
470 if (GetParam().proxy_type == SPDY) {
471 InitializeSpdySsl();
473 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
475 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
476 &pool_, BoundNetLog());
477 EXPECT_EQ(ERR_IO_PENDING, rv);
478 EXPECT_FALSE(handle_.is_initialized());
479 EXPECT_FALSE(handle_.socket());
481 EXPECT_EQ(ERR_PROXY_CERTIFICATE_INVALID, callback_.WaitForResult());
483 EXPECT_FALSE(handle_.is_initialized());
484 EXPECT_FALSE(handle_.socket());
487 TEST_P(HttpProxyClientSocketPoolTest, SslClientAuth) {
488 if (GetParam().proxy_type == HTTP) return;
489 data_.reset(new DeterministicSocketData(NULL, 0, NULL, 0));
490 data_->set_connect_data(MockConnect(ASYNC, OK));
491 socket_factory()->AddSocketDataProvider(data_.get());
493 ssl_data_.reset(new SSLSocketDataProvider(ASYNC,
494 ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
495 if (GetParam().proxy_type == SPDY) {
496 InitializeSpdySsl();
498 socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
500 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
501 &pool_, BoundNetLog());
502 EXPECT_EQ(ERR_IO_PENDING, rv);
503 EXPECT_FALSE(handle_.is_initialized());
504 EXPECT_FALSE(handle_.socket());
506 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, callback_.WaitForResult());
508 EXPECT_FALSE(handle_.is_initialized());
509 EXPECT_FALSE(handle_.socket());
512 TEST_P(HttpProxyClientSocketPoolTest, TunnelUnexpectedClose) {
513 MockWrite writes[] = {
514 MockWrite(ASYNC, 0,
515 "CONNECT www.google.com:443 HTTP/1.1\r\n"
516 "Host: www.google.com\r\n"
517 "Proxy-Connection: keep-alive\r\n"
518 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
520 MockRead reads[] = {
521 MockRead(ASYNC, 1, "HTTP/1.1 200 Conn"),
522 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2),
524 scoped_ptr<SpdyFrame> req(
525 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
526 MockWrite spdy_writes[] = {
527 CreateMockWrite(*req, 0, ASYNC)
529 MockRead spdy_reads[] = {
530 MockRead(ASYNC, ERR_CONNECTION_CLOSED, 1),
533 Initialize(reads, arraysize(reads), writes, arraysize(writes),
534 spdy_reads, arraysize(spdy_reads), spdy_writes,
535 arraysize(spdy_writes));
536 AddAuthToCache();
538 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
539 &pool_, BoundNetLog());
540 EXPECT_EQ(ERR_IO_PENDING, rv);
541 EXPECT_FALSE(handle_.is_initialized());
542 EXPECT_FALSE(handle_.socket());
544 data_->RunFor(3);
545 if (GetParam().proxy_type == SPDY) {
546 // SPDY cannot process a headers block unless it's complete and so it
547 // returns ERR_CONNECTION_CLOSED in this case.
548 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
549 } else {
550 EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, callback_.WaitForResult());
552 EXPECT_FALSE(handle_.is_initialized());
553 EXPECT_FALSE(handle_.socket());
556 TEST_P(HttpProxyClientSocketPoolTest, Tunnel1xxResponse) {
557 // Tests that 1xx responses are rejected for a CONNECT request.
558 if (GetParam().proxy_type == SPDY) {
559 // SPDY doesn't have 1xx responses.
560 return;
563 MockWrite writes[] = {
564 MockWrite(ASYNC, 0,
565 "CONNECT www.google.com:443 HTTP/1.1\r\n"
566 "Host: www.google.com\r\n"
567 "Proxy-Connection: keep-alive\r\n\r\n"),
569 MockRead reads[] = {
570 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
571 MockRead(ASYNC, 2, "HTTP/1.1 200 Connection Established\r\n\r\n"),
574 Initialize(reads, arraysize(reads), writes, arraysize(writes),
575 NULL, 0, NULL, 0);
577 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
578 &pool_, BoundNetLog());
579 EXPECT_EQ(ERR_IO_PENDING, rv);
580 EXPECT_FALSE(handle_.is_initialized());
581 EXPECT_FALSE(handle_.socket());
583 data_->RunFor(2);
584 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
587 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupError) {
588 MockWrite writes[] = {
589 MockWrite(ASYNC, 0,
590 "CONNECT www.google.com:443 HTTP/1.1\r\n"
591 "Host: www.google.com\r\n"
592 "Proxy-Connection: keep-alive\r\n"
593 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
595 MockRead reads[] = {
596 MockRead(ASYNC, 1, "HTTP/1.1 304 Not Modified\r\n\r\n"),
598 scoped_ptr<SpdyFrame> req(
599 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
600 scoped_ptr<SpdyFrame> rst(
601 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
602 MockWrite spdy_writes[] = {
603 CreateMockWrite(*req, 0, ASYNC),
604 CreateMockWrite(*rst, 2, ASYNC),
606 scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdySynReplyError(1));
607 MockRead spdy_reads[] = {
608 CreateMockRead(*resp, 1, ASYNC),
609 MockRead(ASYNC, 0, 3),
612 Initialize(reads, arraysize(reads), writes, arraysize(writes),
613 spdy_reads, arraysize(spdy_reads), spdy_writes,
614 arraysize(spdy_writes));
615 AddAuthToCache();
617 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
618 &pool_, BoundNetLog());
619 EXPECT_EQ(ERR_IO_PENDING, rv);
620 EXPECT_FALSE(handle_.is_initialized());
621 EXPECT_FALSE(handle_.socket());
623 data_->RunFor(2);
625 rv = callback_.WaitForResult();
626 // All Proxy CONNECT responses are not trustworthy
627 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
628 EXPECT_FALSE(handle_.is_initialized());
629 EXPECT_FALSE(handle_.socket());
632 TEST_P(HttpProxyClientSocketPoolTest, TunnelSetupRedirect) {
633 const std::string redirectTarget = "https://foo.google.com/";
635 const std::string responseText = "HTTP/1.1 302 Found\r\n"
636 "Location: " + redirectTarget + "\r\n"
637 "Set-Cookie: foo=bar\r\n"
638 "\r\n";
639 MockWrite writes[] = {
640 MockWrite(ASYNC, 0,
641 "CONNECT www.google.com:443 HTTP/1.1\r\n"
642 "Host: www.google.com\r\n"
643 "Proxy-Connection: keep-alive\r\n"
644 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
646 MockRead reads[] = {
647 MockRead(ASYNC, 1, responseText.c_str()),
649 scoped_ptr<SpdyFrame> req(
650 spdy_util_.ConstructSpdyConnect(kAuthHeaders, kAuthHeadersSize, 1, LOW));
651 scoped_ptr<SpdyFrame> rst(
652 spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_CANCEL));
654 MockWrite spdy_writes[] = {
655 CreateMockWrite(*req, 0, ASYNC),
656 CreateMockWrite(*rst, 3, ASYNC),
659 const char* const responseHeaders[] = {
660 "location", redirectTarget.c_str(),
661 "set-cookie", "foo=bar",
663 const int responseHeadersSize = arraysize(responseHeaders) / 2;
664 scoped_ptr<SpdyFrame> resp(
665 spdy_util_.ConstructSpdySynReplyError(
666 "302 Found",
667 responseHeaders, responseHeadersSize,
668 1));
669 MockRead spdy_reads[] = {
670 CreateMockRead(*resp, 1, ASYNC),
671 MockRead(ASYNC, 0, 2),
674 Initialize(reads, arraysize(reads), writes, arraysize(writes),
675 spdy_reads, arraysize(spdy_reads), spdy_writes,
676 arraysize(spdy_writes));
677 AddAuthToCache();
679 int rv = handle_.Init("a", CreateTunnelParams(), LOW, callback_.callback(),
680 &pool_, BoundNetLog());
681 EXPECT_EQ(ERR_IO_PENDING, rv);
682 EXPECT_FALSE(handle_.is_initialized());
683 EXPECT_FALSE(handle_.socket());
685 data_->RunFor(2);
687 rv = callback_.WaitForResult();
689 if (GetParam().proxy_type == HTTP) {
690 // We don't trust 302 responses to CONNECT from HTTP proxies.
691 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
692 EXPECT_FALSE(handle_.is_initialized());
693 EXPECT_FALSE(handle_.socket());
694 } else {
695 // Expect ProxyClientSocket to return the proxy's response, sanitized.
696 EXPECT_EQ(ERR_HTTPS_PROXY_TUNNEL_RESPONSE, rv);
697 EXPECT_TRUE(handle_.is_initialized());
698 ASSERT_TRUE(handle_.socket());
700 const ProxyClientSocket* tunnel_socket =
701 static_cast<ProxyClientSocket*>(handle_.socket());
702 const HttpResponseInfo* response = tunnel_socket->GetConnectResponseInfo();
703 const HttpResponseHeaders* headers = response->headers.get();
705 // Make sure Set-Cookie header was stripped.
706 EXPECT_FALSE(headers->HasHeader("set-cookie"));
708 // Make sure Content-Length: 0 header was added.
709 EXPECT_TRUE(headers->HasHeaderValue("content-length", "0"));
711 // Make sure Location header was included and correct.
712 std::string location;
713 EXPECT_TRUE(headers->IsRedirect(&location));
714 EXPECT_EQ(location, redirectTarget);
718 // It would be nice to also test the timeouts in HttpProxyClientSocketPool.
720 } // namespace
722 } // namespace net