| Index: net/http/http_stream_factory_impl_unittest.cc
|
| diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
|
| index 2448768a001fffef2a04051f1816a9518ff1ff41..f01ec2f65e55be9fe017e55fb9b9dfafcb9f12fe 100644
|
| --- a/net/http/http_stream_factory_impl_unittest.cc
|
| +++ b/net/http/http_stream_factory_impl_unittest.cc
|
| @@ -14,6 +14,7 @@
|
| #include "base/run_loop.h"
|
| #include "net/base/port_util.h"
|
| #include "net/base/test_completion_callback.h"
|
| +#include "net/base/test_proxy_delegate.h"
|
| #include "net/cert/ct_policy_enforcer.h"
|
| #include "net/cert/mock_cert_verifier.h"
|
| #include "net/cert/multi_log_ct_verifier.h"
|
| @@ -684,25 +685,30 @@ TEST_F(HttpStreamFactoryTest, JobNotifiesProxy) {
|
| EXPECT_TRUE(iter != retry_info.end());
|
| }
|
|
|
| -TEST_F(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) {
|
| - const int mock_error[] = {ERR_PROXY_CONNECTION_FAILED,
|
| - ERR_NAME_NOT_RESOLVED,
|
| - ERR_INTERNET_DISCONNECTED,
|
| - ERR_ADDRESS_UNREACHABLE,
|
| - ERR_CONNECTION_CLOSED,
|
| - ERR_CONNECTION_TIMED_OUT,
|
| - ERR_CONNECTION_RESET,
|
| - ERR_CONNECTION_REFUSED,
|
| - ERR_CONNECTION_ABORTED,
|
| - ERR_TIMED_OUT,
|
| - ERR_TUNNEL_CONNECTION_FAILED,
|
| - ERR_SOCKS_CONNECTION_FAILED,
|
| - ERR_PROXY_CERTIFICATE_INVALID,
|
| - ERR_QUIC_PROTOCOL_ERROR,
|
| - ERR_QUIC_HANDSHAKE_FAILED,
|
| - ERR_SSL_PROTOCOL_ERROR,
|
| - ERR_MSG_TOO_BIG};
|
| - for (size_t i = 0; i < arraysize(mock_error); ++i) {
|
| +// List of errors that are used in the tests related to QUIC proxy.
|
| +const int quic_proxy_test_mock_errors[] = {
|
| + ERR_PROXY_CONNECTION_FAILED,
|
| + ERR_NAME_NOT_RESOLVED,
|
| + ERR_INTERNET_DISCONNECTED,
|
| + ERR_ADDRESS_UNREACHABLE,
|
| + ERR_CONNECTION_CLOSED,
|
| + ERR_CONNECTION_TIMED_OUT,
|
| + ERR_CONNECTION_RESET,
|
| + ERR_CONNECTION_REFUSED,
|
| + ERR_CONNECTION_ABORTED,
|
| + ERR_TIMED_OUT,
|
| + ERR_TUNNEL_CONNECTION_FAILED,
|
| + ERR_SOCKS_CONNECTION_FAILED,
|
| + ERR_PROXY_CERTIFICATE_INVALID,
|
| + ERR_QUIC_PROTOCOL_ERROR,
|
| + ERR_QUIC_HANDSHAKE_FAILED,
|
| + ERR_SSL_PROTOCOL_ERROR,
|
| + ERR_MSG_TOO_BIG,
|
| +};
|
| +
|
| +// Tests that a bad QUIC proxy is added to the list of bad proxies.
|
| +TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
|
| + for (size_t i = 0; i < arraysize(quic_proxy_test_mock_errors); ++i) {
|
| std::unique_ptr<ProxyService> proxy_service;
|
| proxy_service =
|
| ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT");
|
| @@ -733,7 +739,8 @@ TEST_F(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) {
|
| session->quic_stream_factory()->set_require_confirmation(false);
|
|
|
| StaticSocketDataProvider socket_data1;
|
| - socket_data1.set_connect_data(MockConnect(ASYNC, mock_error[i]));
|
| + socket_data1.set_connect_data(
|
| + MockConnect(ASYNC, quic_proxy_test_mock_errors[i]));
|
| socket_factory.AddSocketDataProvider(&socket_data1);
|
|
|
| // Second connection attempt succeeds.
|
| @@ -758,11 +765,11 @@ TEST_F(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) {
|
| // The proxy that failed should now be known to the proxy_service as bad.
|
| const ProxyRetryInfoMap& retry_info =
|
| session->proxy_service()->proxy_retry_info();
|
| - EXPECT_EQ(1u, retry_info.size()) << mock_error[i];
|
| + EXPECT_EQ(1u, retry_info.size()) << quic_proxy_test_mock_errors[i];
|
| EXPECT_TRUE(waiter.used_proxy_info().is_direct());
|
|
|
| ProxyRetryInfoMap::const_iterator iter = retry_info.find("quic://bad:99");
|
| - EXPECT_TRUE(iter != retry_info.end()) << mock_error[i];
|
| + EXPECT_TRUE(iter != retry_info.end()) << quic_proxy_test_mock_errors[i];
|
| }
|
| }
|
|
|
| @@ -830,8 +837,246 @@ class MockQuicData {
|
| std::unique_ptr<SequencedSocketData> socket_data_;
|
| };
|
|
|
| +void SetupForQuicAlternativeProxyTest(
|
| + HttpNetworkSession::Params* params,
|
| + MockClientSocketFactory* socket_factory,
|
| + ProxyService* proxy_service,
|
| + TestProxyDelegate* test_proxy_delegate,
|
| + HttpServerPropertiesImpl* http_server_properties,
|
| + MockCertVerifier* cert_verifier,
|
| + CTPolicyEnforcer* ct_policy_enforcer,
|
| + MultiLogCTVerifier* ct_verifier,
|
| + SSLConfigServiceDefaults* ssl_config_service,
|
| + MockHostResolver* host_resolver,
|
| + TransportSecurityState* transport_security_state,
|
| + bool set_alternative_proxy_server) {
|
| + params->enable_quic = true;
|
| + params->quic_disable_preconnect_if_0rtt = false;
|
| + params->client_socket_factory = socket_factory;
|
| + params->host_resolver = host_resolver;
|
| + params->transport_security_state = transport_security_state;
|
| + params->proxy_service = proxy_service;
|
| + params->ssl_config_service = ssl_config_service;
|
| + params->http_server_properties = http_server_properties;
|
| + params->cert_verifier = cert_verifier;
|
| + params->ct_policy_enforcer = ct_policy_enforcer;
|
| + params->cert_transparency_verifier = ct_verifier;
|
| +
|
| + if (set_alternative_proxy_server) {
|
| + test_proxy_delegate->SetAlternativeProxy(
|
| + ProxyServer::FromPacString("QUIC badproxy:99"));
|
| + }
|
| + params->proxy_delegate = test_proxy_delegate;
|
| +}
|
| +
|
| } // namespace
|
|
|
| +// Tests that a HTTPS proxy that supports QUIC alternative proxy server is
|
| +// marked as bad if connecting to both the default proxy and the alternative
|
| +// proxy is unsuccessful.
|
| +TEST_F(HttpStreamFactoryTest, WithQUICAlternativeProxyMarkedAsBad) {
|
| + const bool set_alternative_proxy_server_values[] = {
|
| + false, true,
|
| + };
|
| +
|
| + for (auto mock_error : quic_proxy_test_mock_errors) {
|
| + for (auto set_alternative_proxy_server :
|
| + set_alternative_proxy_server_values) {
|
| + HttpNetworkSession::Params params;
|
| + MockClientSocketFactory socket_factory;
|
| + std::unique_ptr<ProxyService> proxy_service =
|
| + ProxyService::CreateFixedFromPacResult(
|
| + "HTTPS badproxy:99; HTTPS badfallbackproxy:98; DIRECT");
|
| + TestProxyDelegate test_proxy_delegate;
|
| + HttpServerPropertiesImpl http_server_properties;
|
| + MockCertVerifier cert_verifier;
|
| + CTPolicyEnforcer ct_policy_enforcer;
|
| + MultiLogCTVerifier ct_verifier;
|
| + scoped_refptr<SSLConfigServiceDefaults> ssl_config_service(
|
| + new SSLConfigServiceDefaults);
|
| + MockHostResolver host_resolver;
|
| + TransportSecurityState transport_security_state;
|
| + SetupForQuicAlternativeProxyTest(
|
| + ¶ms, &socket_factory, proxy_service.get(), &test_proxy_delegate,
|
| + &http_server_properties, &cert_verifier, &ct_policy_enforcer,
|
| + &ct_verifier, ssl_config_service.get(), &host_resolver,
|
| + &transport_security_state, set_alternative_proxy_server);
|
| +
|
| + std::unique_ptr<HttpNetworkSession> session(
|
| + new HttpNetworkSession(params));
|
| +
|
| + // Before starting the test, verify that there are no proxies marked as
|
| + // bad.
|
| + ASSERT_TRUE(session->proxy_service()->proxy_retry_info().empty())
|
| + << mock_error;
|
| +
|
| + StaticSocketDataProvider socket_data_proxy_main_job;
|
| + socket_data_proxy_main_job.set_connect_data(
|
| + MockConnect(ASYNC, mock_error));
|
| + socket_factory.AddSocketDataProvider(&socket_data_proxy_main_job);
|
| +
|
| + StaticSocketDataProvider socket_data_proxy_alternate_job;
|
| + if (set_alternative_proxy_server) {
|
| + // Mock socket used by the QUIC job.
|
| + socket_data_proxy_alternate_job.set_connect_data(
|
| + MockConnect(ASYNC, mock_error));
|
| + socket_factory.AddSocketDataProvider(&socket_data_proxy_alternate_job);
|
| + }
|
| +
|
| + // When retrying the job using the second proxy (badFallback:98),
|
| + // alternative job must not be created. So, socket data for only the
|
| + // main job is needed.
|
| + StaticSocketDataProvider socket_data_proxy_main_job_2;
|
| + socket_data_proxy_main_job_2.set_connect_data(
|
| + MockConnect(ASYNC, mock_error));
|
| + socket_factory.AddSocketDataProvider(&socket_data_proxy_main_job_2);
|
| +
|
| + // First request would use DIRECT, and succeed.
|
| + StaticSocketDataProvider socket_data_direct_first_request;
|
| + socket_data_direct_first_request.set_connect_data(MockConnect(ASYNC, OK));
|
| + socket_factory.AddSocketDataProvider(&socket_data_direct_first_request);
|
| +
|
| + // Second request would use DIRECT, and succeed.
|
| + StaticSocketDataProvider socket_data_direct_second_request;
|
| + socket_data_direct_second_request.set_connect_data(
|
| + MockConnect(ASYNC, OK));
|
| + socket_factory.AddSocketDataProvider(&socket_data_direct_second_request);
|
| +
|
| + // Now request a stream. It should succeed using the DIRECT.
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://www.google.com");
|
| +
|
| + SSLConfig ssl_config;
|
| + StreamRequestWaiter waiter;
|
| +
|
| + EXPECT_EQ(set_alternative_proxy_server,
|
| + test_proxy_delegate.alternative_proxy_server().is_quic());
|
| +
|
| + // Start two requests. The first request should consume data from
|
| + // |socket_data_proxy_main_job|,
|
| + // |socket_data_proxy_alternate_job| and
|
| + // |socket_data_direct_first_request|. The second request should consume
|
| + // data from |socket_data_direct_second_request|.
|
| + for (size_t i = 0; i < 2; ++i) {
|
| + std::unique_ptr<HttpStreamRequest> request(
|
| + session->http_stream_factory()->RequestStream(
|
| + request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
|
| + BoundNetLog()));
|
| + waiter.WaitForStream();
|
| +
|
| + // The proxy that failed should now be known to the proxy_service as
|
| + // bad.
|
| + const ProxyRetryInfoMap retry_info =
|
| + session->proxy_service()->proxy_retry_info();
|
| + EXPECT_EQ(2u, retry_info.size()) << mock_error;
|
| +
|
| + // Verify that request was fetched without proxy.
|
| + EXPECT_TRUE(waiter.used_proxy_info().is_direct());
|
| +
|
| + EXPECT_NE(retry_info.end(), retry_info.find("https://badproxy:99"));
|
| + EXPECT_NE(retry_info.end(),
|
| + retry_info.find("https://badfallbackproxy:98"));
|
| +
|
| + // If alternative proxy server was specified, it should have been marked
|
| + // as invalid so that it is not used for subsequent requests.
|
| + EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_valid());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Tests that a HTTPS proxy that supports QUIC alternative proxy server is
|
| +// not marked as bad if only the alternative proxy server job fails.
|
| +TEST_F(HttpStreamFactoryTest, WithQUICAlternativeProxyNotMarkedAsBad) {
|
| + for (auto mock_error : quic_proxy_test_mock_errors) {
|
| + HttpNetworkSession::Params params;
|
| + MockClientSocketFactory socket_factory;
|
| + std::unique_ptr<ProxyService> proxy_service =
|
| + ProxyService::CreateFixedFromPacResult("HTTPS badproxy:99; DIRECT");
|
| + TestProxyDelegate test_proxy_delegate;
|
| + HttpServerPropertiesImpl http_server_properties;
|
| + MockCertVerifier cert_verifier;
|
| + CTPolicyEnforcer ct_policy_enforcer;
|
| + MultiLogCTVerifier ct_verifier;
|
| +
|
| + scoped_refptr<SSLConfigServiceDefaults> ssl_config_service(
|
| + new SSLConfigServiceDefaults);
|
| + MockHostResolver host_resolver;
|
| + TransportSecurityState transport_security_state;
|
| +
|
| + SetupForQuicAlternativeProxyTest(
|
| + ¶ms, &socket_factory, proxy_service.get(), &test_proxy_delegate,
|
| + &http_server_properties, &cert_verifier, &ct_policy_enforcer,
|
| + &ct_verifier, ssl_config_service.get(), &host_resolver,
|
| + &transport_security_state, true);
|
| +
|
| + HostPortPair host_port_pair("badproxy", 99);
|
| + std::unique_ptr<HttpNetworkSession> session(new HttpNetworkSession(params));
|
| +
|
| + // Before starting the test, verify that there are no proxies marked as
|
| + // bad.
|
| + ASSERT_TRUE(session->proxy_service()->proxy_retry_info().empty())
|
| + << mock_error;
|
| +
|
| + StaticSocketDataProvider socket_data_proxy_main_job;
|
| + socket_data_proxy_main_job.set_connect_data(MockConnect(ASYNC, mock_error));
|
| + socket_factory.AddSocketDataProvider(&socket_data_proxy_main_job);
|
| +
|
| + SSLSocketDataProvider ssl_data(ASYNC, OK);
|
| +
|
| + // Next connection attempt would use HTTPS proxy, and succeed.
|
| + StaticSocketDataProvider socket_data_https_first;
|
| + socket_data_https_first.set_connect_data(MockConnect(ASYNC, OK));
|
| + socket_factory.AddSocketDataProvider(&socket_data_https_first);
|
| + socket_factory.AddSSLSocketDataProvider(&ssl_data);
|
| +
|
| + // Next connection attempt would use HTTPS proxy, and succeed.
|
| + StaticSocketDataProvider socket_data_https_second;
|
| + socket_data_https_second.set_connect_data(MockConnect(ASYNC, OK));
|
| + socket_factory.AddSocketDataProvider(&socket_data_https_second);
|
| + socket_factory.AddSSLSocketDataProvider(&ssl_data);
|
| +
|
| + // Now request a stream. It should succeed using the second proxy in the
|
| + // list.
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://www.google.com");
|
| +
|
| + SSLConfig ssl_config;
|
| + StreamRequestWaiter waiter;
|
| +
|
| + EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
|
| +
|
| + // Start two requests. The first request should consume data from
|
| + // |socket_data_proxy_main_job| and |socket_data_https_first|.
|
| + // The second request should consume data from |socket_data_https_second|.
|
| + for (size_t i = 0; i < 2; ++i) {
|
| + std::unique_ptr<HttpStreamRequest> request(
|
| + session->http_stream_factory()->RequestStream(
|
| + request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
|
| + BoundNetLog()));
|
| + waiter.WaitForStream();
|
| +
|
| + // The proxy that failed should now be known to the proxy_service as
|
| + // bad.
|
| + const ProxyRetryInfoMap retry_info =
|
| + session->proxy_service()->proxy_retry_info();
|
| + // Proxy should not be marked as bad.
|
| + EXPECT_EQ(0u, retry_info.size()) << mock_error;
|
| + // Verify that request was fetched using proxy.
|
| + EXPECT_TRUE(waiter.used_proxy_info().is_https());
|
| + EXPECT_TRUE(host_port_pair.Equals(
|
| + waiter.used_proxy_info().proxy_server().host_port_pair()));
|
| + net::ProxyServer proxy_server;
|
| +
|
| + // Alternative proxy server should be marked as invalid so that it is
|
| + // not used for subsequent requests.
|
| + EXPECT_FALSE(test_proxy_delegate.alternative_proxy_server().is_quic());
|
| + }
|
| + }
|
| +}
|
| +
|
| TEST_F(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad) {
|
| // Checks if a
|
| std::unique_ptr<ProxyService> proxy_service;
|
|
|