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

Unified Diff: net/quic/chromium/quic_network_transaction_unittest.cc

Issue 2595413002: Race preconnects to HTTP2 proxies that support alternate proxies
Patch Set: Rebased, rch comments Created 3 years, 11 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/quic/chromium/quic_network_transaction_unittest.cc
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index e5e8648d1ea4193568dffa6953c76275e513487d..c99526f3599422ff6f118adcb2e96e79265a115e 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -700,6 +700,67 @@ class QuicNetworkTransactionTest
SendRequestAndExpectHttpResponseFromProxy("hello from http", true, 443);
}
+ // Preconnects to a HTTPS proxy with a QUIC alternative proxy. Verifies that
+ // if the alternative proxy job returns |error_code|, the preconnection still
+ // succeeds.
+ void TestAlternativeProxyPreconnect(int error_code) {
+ base::HistogramTester histogram_tester;
+ // Data for the alternative proxy server job.
+ MockWrite quic_writes[] = {MockWrite(SYNCHRONOUS, error_code, 1)};
+ MockRead quic_reads[] = {
+ MockRead(SYNCHRONOUS, error_code, 0),
+ };
+
+ SequencedSocketData quic_data(quic_reads, arraysize(quic_reads),
+ quic_writes, arraysize(quic_writes));
+ socket_factory_.AddSocketDataProvider(&quic_data);
+
+ // Main job succeeds and the alternative job fails.
+ // Add data for two requests that will be read by the main job.
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello from http"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)};
+
+ StaticSocketDataProvider http_data_1(http_reads, arraysize(http_reads),
+ nullptr, 0);
+ socket_factory_.AddSocketDataProvider(&http_data_1);
+ socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
+
+ TestProxyDelegate test_proxy_delegate;
+ // Proxy URL is different from the request URL.
+ test_proxy_delegate.set_alternative_proxy_server(
+ ProxyServer::FromPacString("QUIC myproxy.org:443"));
+
+ params_.proxy_delegate = &test_proxy_delegate;
+ params_.race_preconnects_to_http2_proxies = true;
+ proxy_service_ =
+ ProxyService::CreateFixedFromPacResult("HTTPS myproxy.org:443");
+
+ CreateSession();
+ EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_valid());
+
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ // Use a non-cryptographic scheme for the preconnect URL since this will be
+ // fetched via proxy with QUIC as the alternative service.
+ request_info.url = GURL("http://www.google.com");
+
+ session_->http_stream_factory()->PreconnectStreams(1 /*num_streams*/,
+ request_info);
+ base::RunLoop().RunUntilIdle();
+
+ // Even through the alternative proxy server job failed, the proxy should
+ // not be marked as bad since the main job succeeded.
+ EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
+
+ // The alternative proxy server should no longer be in use.
+ EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_valid());
+
+ histogram_tester.ExpectTotalCount(
+ "Net.QuicAlternativeProxy.PreconnectRace.FirstJobFinished", 1);
+ }
+
const QuicVersion version_;
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
MockClock* clock_; // Owned by QuicStreamFactory after CreateSession.
@@ -1853,6 +1914,65 @@ TEST_P(QuicNetworkTransactionTest, QuicProxyWithRacing) {
1);
}
+// Tests that the connection to an HTTPS proxy is raced with an available
+// alternative proxy server.
+TEST_P(QuicNetworkTransactionTest, QuicProxyWithRacingForPreconnect) {
+ base::HistogramTester histogram_tester;
+ proxy_service_ =
+ ProxyService::CreateFixedFromPacResult("HTTPS mail.example.org:443");
+
+ MockQuicData mock_quic_data;
+ QuicStreamOffset header_stream_offset = 0;
+ mock_quic_data.AddWrite(ConstructSettingsPacket(
+ 1, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize,
+ &header_stream_offset));
+ mock_quic_data.AddWrite(ConstructClientRequestHeadersPacket(
+ 2, kClientDataStreamId1, true, true,
+ GetRequestHeaders("GET", "http", "/"), &header_stream_offset));
+ mock_quic_data.AddRead(ConstructServerResponseHeadersPacket(
+ 1, kClientDataStreamId1, false, false, GetResponseHeaders("200 OK")));
+ mock_quic_data.AddRead(ConstructServerDataPacket(2, kClientDataStreamId1,
+ false, true, 0, "hello!"));
+ mock_quic_data.AddWrite(ConstructClientAckPacket(3, 2, 1));
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
+ mock_quic_data.AddRead(ASYNC, 0); // EOF
+
+ mock_quic_data.AddSocketDataToFactory(&socket_factory_);
+
+ // There is no need to set up main job, because no attempt will be made to
+ // speak to the proxy over TCP.
+ params_.enable_quic_alternative_service_with_different_host = false;
+ TestProxyDelegate test_proxy_delegate;
+ const HostPortPair host_port_pair("mail.example.org", 443);
+
+ test_proxy_delegate.set_alternative_proxy_server(
+ ProxyServer::FromPacString("QUIC mail.example.org:443"));
+ params_.proxy_delegate = &test_proxy_delegate;
+ params_.race_preconnects_to_http2_proxies = true;
+ CreateSession();
+ EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
+
+ // The main job needs to hang in order to guarantee that the alternative
+ // proxy server job will "win".
+ AddHangingNonAlternateProtocolSocketData();
+
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://www.google.com");
+
+ session_->http_stream_factory()->PreconnectStreams(1 /* num_streams */,
+ request_info);
+ base::RunLoop().RunUntilIdle();
+ histogram_tester.ExpectTotalCount(
+ "Net.QuicAlternativeProxy.PreconnectRace.FirstJobFinished", 1);
+
+ // Verify that the alternative proxy server is not marked as broken.
+ EXPECT_TRUE(test_proxy_delegate.alternative_proxy_server().is_quic());
+
+ // Verify that the proxy server is not marked as broken.
+ EXPECT_TRUE(session_->proxy_service()->proxy_retry_info().empty());
+}
+
TEST_P(QuicNetworkTransactionTest, HungAlternativeService) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
@@ -2515,6 +2635,38 @@ TEST_P(QuicNetworkTransactionTest, BrokenAlternativeProxyAddressUnreachable) {
TestAlternativeProxy(ERR_ADDRESS_UNREACHABLE);
}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxySocketNotConnectedPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_SOCKET_NOT_CONNECTED);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyConnectionFailedPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_CONNECTION_FAILED);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyConnectionTimedOutPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_CONNECTION_TIMED_OUT);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyConnectionRefusedPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_CONNECTION_REFUSED);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyQuicHandshakeFailedPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_QUIC_HANDSHAKE_FAILED);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyQuicProtocolErrorPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_QUIC_PROTOCOL_ERROR);
+}
+TEST_P(QuicNetworkTransactionTest, BrokenAlternativeProxyIOPendingPreconnect) {
+ TestAlternativeProxyPreconnect(ERR_IO_PENDING);
+}
+TEST_P(QuicNetworkTransactionTest,
+ BrokenAlternativeProxyAddressUnreachablePreconnect) {
+ TestAlternativeProxyPreconnect(ERR_ADDRESS_UNREACHABLE);
+}
+
TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnectProxy) {
MockQuicData mock_quic_data;
mock_quic_data.AddSynchronousRead(ConstructServerConnectionClosePacket(1));

Powered by Google App Engine
This is Rietveld 408576698