| Index: net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| index 395372995aeba3dba4f535ea7c029862ba479aae..dad4a1add61b761e421953a9127869bd9ca9465f 100644
|
| --- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| +++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| @@ -8,6 +8,8 @@
|
|
|
| #include "base/memory/ptr_util.h"
|
| #include "base/run_loop.h"
|
| +#include "base/threading/platform_thread.h"
|
| +#include "net/base/test_proxy_delegate.h"
|
| #include "net/dns/mock_host_resolver.h"
|
| #include "net/http/http_basic_stream.h"
|
| #include "net/http/http_stream_factory_impl_request.h"
|
| @@ -18,6 +20,7 @@
|
| #include "net/proxy/proxy_service.h"
|
| #include "net/quic/test_tools/quic_stream_factory_peer.h"
|
| #include "net/spdy/spdy_test_util_common.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gmock_mutant.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -97,6 +100,11 @@ class JobControllerPeer {
|
| const base::TimeDelta& delay) {
|
| EXPECT_EQ(delay, job_controller->main_job_wait_time_);
|
| }
|
| +
|
| + static bool main_job_is_blocked(
|
| + HttpStreamFactoryImpl::JobController* job_controller) {
|
| + return job_controller->main_job_is_blocked_;
|
| + }
|
| };
|
|
|
| class HttpStreamFactoryImplJobControllerTest
|
| @@ -108,7 +116,21 @@ class HttpStreamFactoryImplJobControllerTest
|
| session_deps_.enable_quic = true;
|
| }
|
|
|
| - void Initialize() {
|
| + void Initialize(bool use_alternative_proxy) {
|
| + std::unique_ptr<TestProxyDelegate> test_proxy_delegate(
|
| + new TestProxyDelegate());
|
| + test_proxy_delegate_ = test_proxy_delegate.get();
|
| +
|
| + test_proxy_delegate->set_alternative_proxy_server(
|
| + ProxyServer::FromPacString("QUIC myproxy.org:443"));
|
| + EXPECT_TRUE(test_proxy_delegate->alternative_proxy_server().is_quic());
|
| + session_deps_.proxy_delegate.reset(test_proxy_delegate.release());
|
| +
|
| + if (use_alternative_proxy) {
|
| + std::unique_ptr<ProxyService> proxy_service =
|
| + ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
|
| + session_deps_.proxy_service.reset(proxy_service.release());
|
| + }
|
| session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| factory_ =
|
| static_cast<HttpStreamFactoryImpl*>(session_->http_stream_factory());
|
| @@ -117,6 +139,10 @@ class HttpStreamFactoryImplJobControllerTest
|
| HttpStreamFactoryImplPeer::AddJobController(factory_, job_controller_);
|
| }
|
|
|
| + TestProxyDelegate* test_proxy_delegate() const {
|
| + return test_proxy_delegate_;
|
| + }
|
| +
|
| ~HttpStreamFactoryImplJobControllerTest() {}
|
|
|
| void SetAlternativeService(const HttpRequestInfo& request_info,
|
| @@ -128,6 +154,8 @@ class HttpStreamFactoryImplJobControllerTest
|
| server, alternative_service, expiration);
|
| }
|
|
|
| + // Not owned by |this|.
|
| + TestProxyDelegate* test_proxy_delegate_;
|
| TestJobFactory job_factory_;
|
| MockHttpStreamRequestDelegate request_delegate_;
|
| SpdySessionDependencies session_deps_;
|
| @@ -149,7 +177,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -179,7 +207,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -213,7 +241,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, CancelJobsBeforeBinding) {
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -246,7 +274,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, OnStreamFailedForBothJobs) {
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -290,7 +318,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -342,7 +370,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -390,7 +418,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, GetLoadStateAfterMainJobFailed) {
|
| session_deps_.proxy_service.reset(new ProxyService(
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -441,7 +469,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, DoNotResumeMainJobBeforeWait) {
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(new FailingProxyResolverFactory), nullptr));
|
|
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -467,7 +495,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, DoNotResumeMainJobBeforeWait) {
|
| TEST_F(HttpStreamFactoryImplJobControllerTest, InvalidPortForQuic) {
|
| // Using a restricted port 101 for QUIC should fail and the alternative job
|
| // should post OnStreamFailedCall on the controller to resume the main job.
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -509,7 +537,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| session_deps_.host_resolver.reset(host_resolver);
|
| session_deps_.host_resolver->set_synchronous_mode(false);
|
|
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -573,7 +601,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest,
|
| base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| base::WrapUnique(proxy_resolver_factory), nullptr));
|
|
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| @@ -626,7 +654,7 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
|
| HangingResolver* resolver = new HangingResolver();
|
| session_deps_.host_resolver.reset(resolver);
|
|
|
| - Initialize();
|
| + Initialize(false);
|
|
|
| // Enable delayed TCP and set time delay for waiting job.
|
| QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
|
| @@ -663,4 +691,171 @@ TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCP) {
|
|
|
| base::RunLoop().RunUntilIdle();
|
| }
|
| +
|
| +// Verifies that the alternative proxy server job is not created if the URL
|
| +// scheme is HTTPS.
|
| +TEST_F(HttpStreamFactoryImplJobControllerTest, HttpsURL) {
|
| + // Using hanging resolver will cause the alternative job to hang indefinitely.
|
| + HangingResolver* resolver = new HangingResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize(true);
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("https://mail.example.org/");
|
| +
|
| + request_.reset(
|
| + job_controller_->Start(request_info, &request_delegate_, nullptr,
|
| + BoundNetLog(), HttpStreamRequest::HTTP_STREAM,
|
| + DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
|
| + EXPECT_TRUE(job_controller_->main_job());
|
| + EXPECT_FALSE(job_controller_->main_job()->is_waiting());
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_EQ(0, test_proxy_delegate()->get_alternative_proxy_invocations());
|
| +}
|
| +
|
| +// Verifies that the alternative proxy server job is not created if the main job
|
| +// does not fetch the resource through a proxy.
|
| +TEST_F(HttpStreamFactoryImplJobControllerTest, HttpURLWithNoProxy) {
|
| + // Using hanging resolver will cause the alternative job to hang indefinitely.
|
| + HangingResolver* resolver = new HangingResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize(false);
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://mail.example.org/");
|
| +
|
| + request_.reset(
|
| + job_controller_->Start(request_info, &request_delegate_, nullptr,
|
| + BoundNetLog(), HttpStreamRequest::HTTP_STREAM,
|
| + DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
|
| + EXPECT_TRUE(job_controller_->main_job());
|
| + EXPECT_FALSE(job_controller_->main_job()->is_waiting());
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(0);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_EQ(0, test_proxy_delegate()->get_alternative_proxy_invocations());
|
| +}
|
| +
|
| +// Verifies that the main job is resumed properly after a delay when the
|
| +// alternative proxy server job hangs.
|
| +TEST_F(HttpStreamFactoryImplJobControllerTest, DelayedTCPAlternativeProxy) {
|
| + // Using hanging resolver will cause the alternative job to hang indefinitely.
|
| + HangingResolver* resolver = new HangingResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize(true);
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
|
| +
|
| + // Enable delayed TCP and set time delay for waiting job.
|
| + QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
|
| + test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true);
|
| + quic_stream_factory->set_require_confirmation(false);
|
| + ServerNetworkStats stats1;
|
| + stats1.srtt = base::TimeDelta::FromMicroseconds(10);
|
| + session_->http_server_properties()->SetServerNetworkStats(
|
| + url::SchemeHostPort(GURL("https://myproxy.org")), stats1);
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://mail.example.org/");
|
| +
|
| + request_.reset(
|
| + job_controller_->Start(request_info, &request_delegate_, nullptr,
|
| + BoundNetLog(), HttpStreamRequest::HTTP_STREAM,
|
| + DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
|
| + EXPECT_TRUE(job_controller_->main_job());
|
| + EXPECT_TRUE(job_controller_->main_job()->is_waiting());
|
| + EXPECT_TRUE(job_controller_->alternative_job());
|
| + EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_));
|
| +
|
| + // The alternative proxy server job stalls when connecting to the alternative
|
| + // proxy server, and controller should resume the main job after delay.
|
| + // Verify the waiting time for delayed main job.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume())
|
| + .WillOnce(Invoke(testing::CreateFunctor(
|
| + &JobControllerPeer::VerifyWaitingTimeForMainJob, job_controller_,
|
| + base::TimeDelta::FromMicroseconds(15))));
|
| +
|
| + // This message loop should cause the alternative proxy server job to start,
|
| + // and schedule resumption of the main job.
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
|
| +
|
| + // Wait for the Resume to post.
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
|
| +
|
| + // This message loop should cause the main job to resume.
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_));
|
| +
|
| + JobControllerPeer::VerifyWaitingTimeForMainJob(
|
| + job_controller_, base::TimeDelta::FromMicroseconds(0));
|
| +
|
| + // Since the main job did not complete successfully, the alternative proxy
|
| + // server should not be marked as bad.
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_valid());
|
| + EXPECT_EQ(1, test_proxy_delegate()->get_alternative_proxy_invocations());
|
| +}
|
| +
|
| +// Verifies that the alternative proxy server job fails immediately, and the
|
| +// main job is not blocked.
|
| +TEST_F(HttpStreamFactoryImplJobControllerTest, FailAlternativeProxy) {
|
| + // Using failing resolver will cause the alternative job to fail.
|
| + FailingHostResolver* resolver = new FailingHostResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize(true);
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_quic());
|
| +
|
| + // Enable delayed TCP and set time delay for waiting job.
|
| + QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
|
| + test::QuicStreamFactoryPeer::SetDelayTcpRace(quic_stream_factory, true);
|
| + quic_stream_factory->set_require_confirmation(false);
|
| + ServerNetworkStats stats1;
|
| + stats1.srtt = base::TimeDelta::FromMicroseconds(300 * 1000);
|
| + session_->http_server_properties()->SetServerNetworkStats(
|
| + url::SchemeHostPort(GURL("https://myproxy.org")), stats1);
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://mail.example.org/");
|
| +
|
| + request_.reset(
|
| + job_controller_->Start(request_info, &request_delegate_, nullptr,
|
| + BoundNetLog(), HttpStreamRequest::HTTP_STREAM,
|
| + DEFAULT_PRIORITY, SSLConfig(), SSLConfig()));
|
| + EXPECT_TRUE(job_controller_->main_job()->is_waiting());
|
| + EXPECT_TRUE(job_controller_->alternative_job());
|
| +
|
| + EXPECT_CALL(request_delegate_, OnStreamReady(_, _, _)).Times(0);
|
| + EXPECT_CALL(*job_factory_.main_job(), MarkOtherJobComplete(_)).Times(1);
|
| +
|
| + // Since the alternative proxy server job is started in the next message loop,
|
| + // the main job would remain blocked until the alternative proxy starts, and
|
| + // fails.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume())
|
| + .WillOnce(Invoke(testing::CreateFunctor(
|
| + &JobControllerPeer::VerifyWaitingTimeForMainJob, job_controller_,
|
| + base::TimeDelta::FromMicroseconds(0))));
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| + EXPECT_TRUE(job_controller_->main_job()->is_waiting());
|
| + // Since the main job did not complete successfully, the alternative proxy
|
| + // server should not be marked as bad.
|
| + EXPECT_TRUE(test_proxy_delegate()->alternative_proxy_server().is_valid());
|
| + EXPECT_EQ(1, test_proxy_delegate()->get_alternative_proxy_invocations());
|
| +}
|
| +
|
| } // namespace net
|
|
|