Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Unified Diff: net/http/http_stream_factory_impl_job_controller_unittest.cc

Issue 2260623002: Race TCP connection to proxies with QUIC connections (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..fc1495ed11f4f3d6201a10a7ad421e3c0acb0067 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,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.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 +19,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"
@@ -108,7 +110,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 +133,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 +148,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 +171,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 +201,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 +235,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 +268,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 +312,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 +364,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 +412,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 +463,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 +489,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 +531,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 +595,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 +648,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 +685,156 @@ 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());
+
+ // 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))));
+
+ base::RunLoop().RunUntilIdle();
+ // 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

Powered by Google App Engine
This is Rietveld 408576698