| 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 bd94d7ddc3fa89cdb49f8f5847f58e79e3994577..67415fd3d5dbc1b99eaf892efaab6b65c85ee960 100644
|
| --- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| +++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
|
| @@ -6,9 +6,13 @@
|
|
|
| #include <memory>
|
|
|
| +#include "base/run_loop.cc"
|
| +#include "net/dns/mock_host_resolver.h"
|
| #include "net/http/http_basic_stream.h"
|
| #include "net/http/http_stream_factory_impl_request.h"
|
| #include "net/http/http_stream_factory_test_util.h"
|
| +#include "net/proxy/mock_proxy_resolver.h"
|
| +#include "net/proxy/proxy_config_service_fixed.h"
|
| #include "net/proxy/proxy_info.h"
|
| #include "net/proxy/proxy_service.h"
|
| #include "net/spdy/spdy_test_util_common.h"
|
| @@ -28,8 +32,48 @@ void DeleteHttpStreamPointer(const SSLConfig& used_ssl_config,
|
| delete stream;
|
| }
|
|
|
| +class FailingProxyResolverFactory : public ProxyResolverFactory {
|
| + public:
|
| + FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
|
| +
|
| + // ProxyResolverFactory override.
|
| + int CreateProxyResolver(
|
| + const scoped_refptr<ProxyResolverScriptData>& script_data,
|
| + std::unique_ptr<ProxyResolver>* result,
|
| + const CompletionCallback& callback,
|
| + std::unique_ptr<Request>* request) override {
|
| + return ERR_PAC_SCRIPT_FAILED;
|
| + }
|
| +};
|
| +
|
| +class FailingHostResolver : public MockHostResolverBase {
|
| + public:
|
| + FailingHostResolver() : MockHostResolverBase(false /*use_caching*/) {}
|
| + ~FailingHostResolver() override {}
|
| +
|
| + int Resolve(const RequestInfo& info,
|
| + RequestPriority priority,
|
| + AddressList* addresses,
|
| + const CompletionCallback& callback,
|
| + RequestHandle* out_req,
|
| + const BoundNetLog& net_log) override {
|
| + return ERR_NAME_NOT_RESOLVED;
|
| + }
|
| +};
|
| +
|
| } // anonymous namespace
|
|
|
| +class HttpStreamFactoryImplJobPeer {
|
| + public:
|
| + static void Start(HttpStreamFactoryImpl::Job* job,
|
| + HttpStreamRequest::StreamType stream_type) {
|
| + // Start() is mocked for MockHttpStreamFactoryImplJob.
|
| + // This is the alternative method to invoke real Start() method on Job.
|
| + job->stream_type_ = stream_type;
|
| + job->StartInternal();
|
| + }
|
| +};
|
| +
|
| class HttpStreamFactoryImplJobControllerTest
|
| : public ::testing::Test,
|
| public ::testing::WithParamInterface<NextProto> {
|
| @@ -37,6 +81,9 @@ class HttpStreamFactoryImplJobControllerTest
|
| HttpStreamFactoryImplJobControllerTest()
|
| : session_deps_(GetParam(), ProxyService::CreateDirect()) {
|
| session_deps_.enable_quic = true;
|
| + }
|
| +
|
| + void Initialize() {
|
| session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
|
| factory_ =
|
| static_cast<HttpStreamFactoryImpl*>(session_->http_stream_factory());
|
| @@ -73,6 +120,8 @@ INSTANTIATE_TEST_CASE_P(NextProto,
|
|
|
| TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| OnStreamFailedWithNoAlternativeJob) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("http://www.google.com");
|
| @@ -95,6 +144,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest,
|
|
|
| TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| OnStreamReadyWithNoAlternativeJob) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("http://www.google.com");
|
| @@ -120,6 +171,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| // Test we cancel Jobs correctly when the Request is explicitly canceled
|
| // before any Job is bound to Request.
|
| TEST_P(HttpStreamFactoryImplJobControllerTest, CancelJobsBeforeBinding) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("https://www.google.com");
|
| @@ -143,6 +196,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest, CancelJobsBeforeBinding) {
|
| }
|
|
|
| TEST_P(HttpStreamFactoryImplJobControllerTest, OnStreamFailedForBothJobs) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("https://www.google.com");
|
| @@ -178,6 +233,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest, OnStreamFailedForBothJobs) {
|
|
|
| TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| SecondJobFailsAfterFirstJobSucceeds) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("https://www.google.com");
|
| @@ -220,6 +277,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest,
|
|
|
| TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| SecondJobSucceedsAfterFirstJobFailed) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("https://www.google.com");
|
| @@ -258,6 +317,8 @@ TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| // Regression test for crbug/621069.
|
| // Get load state after main job fails and before alternative job succeeds.
|
| TEST_P(HttpStreamFactoryImplJobControllerTest, GetLoadStateAfterMainJobFailed) {
|
| + Initialize();
|
| +
|
| HttpRequestInfo request_info;
|
| request_info.method = "GET";
|
| request_info.url = GURL("https://www.google.com");
|
| @@ -296,4 +357,200 @@ TEST_P(HttpStreamFactoryImplJobControllerTest, GetLoadStateAfterMainJobFailed) {
|
| ProxyInfo());
|
| }
|
|
|
| +TEST_P(HttpStreamFactoryImplJobControllerTest, InvalidPortToResumeMainJob) {
|
| + Initialize();
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("https://www.google.com");
|
| +
|
| + url::SchemeHostPort server(request_info.url);
|
| + // Using a restricted port 101 for QUIC should fail.
|
| + AlternativeService alternative_service(QUIC, server.host(), 101);
|
| + SetAlternativeService(request_info, alternative_service);
|
| +
|
| + 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_->alternative_job());
|
| +
|
| + // |alternative_job| fails but should not report status to Request.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume(_)).Times(1);
|
| + HttpStreamFactoryImplJobPeer::Start(job_factory_.alternative_job(),
|
| + HttpStreamRequest::HTTP_STREAM);
|
| +
|
| + // Wait until OnStreamFailedCallback is executed on the alternative job.
|
| + EXPECT_CALL(*job_factory_.main_job(), MarkOtherJobComplete(_)).Times(1);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + // |main_job| succeeds and should report status to Request.
|
| + HttpStream* http_stream =
|
| + new HttpBasicStream(new ClientSocketHandle(), false);
|
| + job_factory_.main_job()->SetStream(http_stream);
|
| +
|
| + EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
|
| + .WillOnce(Invoke(DeleteHttpStreamPointer));
|
| + job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
|
| + ProxyInfo());
|
| +}
|
| +
|
| +TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| + FailToResolveProxyToResumeMainJob) {
|
| + // Use failing ProxyResolverFactory which is unable to create ProxyResolver to
|
| + // to stall the alternative job and resume the main job.
|
| + ProxyConfig proxy_config;
|
| + proxy_config.set_auto_detect(true);
|
| + proxy_config.set_pac_mandatory(true);
|
| + session_deps_.proxy_service.reset(new ProxyService(
|
| + base::WrapUnique(new ProxyConfigServiceFixed(proxy_config)),
|
| + base::WrapUnique(new FailingProxyResolverFactory), nullptr));
|
| +
|
| + Initialize();
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("https://www.google.com");
|
| +
|
| + url::SchemeHostPort server(request_info.url);
|
| + AlternativeService alternative_service(QUIC, server.host(), 443);
|
| + SetAlternativeService(request_info, alternative_service);
|
| +
|
| + 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_->alternative_job());
|
| +
|
| + // |alternative_job| fails but should not report status to Request.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume(_)).Times(1);
|
| + HttpStreamFactoryImplJobPeer::Start(job_factory_.alternative_job(),
|
| + HttpStreamRequest::HTTP_STREAM);
|
| +
|
| + // Wait until OnStreamFailedCallback is executed on the alternative job.
|
| + EXPECT_CALL(*job_factory_.main_job(), MarkOtherJobComplete(_)).Times(1);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + // |main_job| succeeds and should report status to Request.
|
| + HttpStream* http_stream =
|
| + new HttpBasicStream(new ClientSocketHandle(), false);
|
| + job_factory_.main_job()->SetStream(http_stream);
|
| +
|
| + EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
|
| + .WillOnce(Invoke(DeleteHttpStreamPointer));
|
| + job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
|
| + ProxyInfo());
|
| +}
|
| +
|
| +TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| + NoAvailableQuicSessionToResumeMainJob) {
|
| + // Use failing HostResolver which is unable to resolve the host name.
|
| + // No QUIC session is created and thus should resume the main job.
|
| + FailingHostResolver* resolver = new FailingHostResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize();
|
| + QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
|
| + DCHECK(quic_stream_factory);
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("https://www.google.com");
|
| +
|
| + url::SchemeHostPort server(request_info.url);
|
| + AlternativeService alternative_service(QUIC, server.host(), 443);
|
| + SetAlternativeService(request_info, alternative_service);
|
| +
|
| + 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_->alternative_job());
|
| +
|
| + // |alternative_job| fails as host resolution fails and should resume the
|
| + // main job.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume(_)).Times(1);
|
| + HttpStreamFactoryImplJobPeer::Start(job_factory_.alternative_job(),
|
| + HttpStreamRequest::HTTP_STREAM);
|
| +
|
| + // Wait until OnStreamFailedCallback is executed on the alternative job.
|
| + // Request shouldn't be notified as the main job is still pending status.
|
| + EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0);
|
| + EXPECT_CALL(*job_factory_.main_job(), MarkOtherJobComplete(_)).Times(1);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + // |main_job| succeeds and should report status to Request.
|
| + HttpStream* http_stream =
|
| + new HttpBasicStream(new ClientSocketHandle(), false);
|
| + job_factory_.main_job()->SetStream(http_stream);
|
| +
|
| + EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
|
| + .WillOnce(Invoke(DeleteHttpStreamPointer));
|
| + job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
|
| + ProxyInfo());
|
| +}
|
| +
|
| +TEST_P(HttpStreamFactoryImplJobControllerTest,
|
| + NoAvailableSpdySessionToResumeMainJob) {
|
| + // Disable QUIC.
|
| + session_deps_.enable_quic = false;
|
| + // Use failing HostResolver which is unable to resolve the host name.
|
| + // No SPDY session is created and thus should resume the main job.
|
| + FailingHostResolver* resolver = new FailingHostResolver();
|
| + session_deps_.host_resolver.reset(resolver);
|
| +
|
| + Initialize();
|
| + QuicStreamFactory* quic_stream_factory = session_->quic_stream_factory();
|
| + DCHECK(quic_stream_factory);
|
| +
|
| + HttpRequestInfo request_info;
|
| + request_info.method = "GET";
|
| + request_info.url = GURL("http://www.google.com");
|
| +
|
| + // Set a SPDY alternative service for the server.
|
| + url::SchemeHostPort server(request_info.url);
|
| + AlternativeService alternative_service(NPN_HTTP_2, server.host(), 443);
|
| + SetAlternativeService(request_info, alternative_service);
|
| +
|
| + 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_->alternative_job());
|
| +
|
| + // |alternative_job| fails as host resolution fails and should resume the
|
| + // main job.
|
| + EXPECT_CALL(*job_factory_.main_job(), Resume(_)).Times(1);
|
| + HttpStreamFactoryImplJobPeer::Start(job_factory_.alternative_job(),
|
| + HttpStreamRequest::HTTP_STREAM);
|
| +
|
| + // Wait until OnStreamFailedCallback is executed on the alternative job.
|
| + // Request shouldn't be notified as the main job is still pending status.
|
| + EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _)).Times(0);
|
| + EXPECT_CALL(*job_factory_.main_job(), MarkOtherJobComplete(_)).Times(1);
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + EXPECT_FALSE(job_controller_->alternative_job());
|
| +
|
| + // |main_job| succeeds and should report status to Request.
|
| + HttpStream* http_stream =
|
| + new HttpBasicStream(new ClientSocketHandle(), false);
|
| + job_factory_.main_job()->SetStream(http_stream);
|
| +
|
| + EXPECT_CALL(request_delegate_, OnStreamReady(_, _, http_stream))
|
| + .WillOnce(Invoke(DeleteHttpStreamPointer));
|
| + job_controller_->OnStreamReady(job_factory_.main_job(), SSLConfig(),
|
| + ProxyInfo());
|
| +}
|
| +
|
| } // namespace net
|
|
|