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

Side by Side Diff: net/quic/chromium/quic_network_transaction_unittest.cc

Issue 2818623002: When HttpNetworkTransaction encounters QUIC errors, retry the request (Closed)
Patch Set: More comments Created 3 years, 8 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 unified diff | Download patch
« no previous file with comments | « net/http/http_network_transaction.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory> 5 #include <memory>
6 #include <ostream> 6 #include <ostream>
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 trans.reset(); 1732 trans.reset();
1733 1733
1734 // Run the QUIC session to completion. 1734 // Run the QUIC session to completion.
1735 quic_task_runner_->RunUntilIdle(); 1735 quic_task_runner_->RunUntilIdle();
1736 1736
1737 ExpectQuicAlternateProtocolMapping(); 1737 ExpectQuicAlternateProtocolMapping();
1738 1738
1739 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); 1739 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
1740 } 1740 }
1741 1741
1742 // Verify that if a QUIC protocol error occurs after the handshake is confirmed
1743 // the request fails with QUIC_PROTOCOL_ERROR.
1744 TEST_P(QuicNetworkTransactionTest, ProtocolErrorAfterHandshakeConfirmed) {
1745 // The request will initially go out over QUIC.
1746 MockQuicData quic_data;
1747 QuicStreamOffset header_stream_offset = 0;
1748 quic_data.AddWrite(ConstructClientRequestHeadersPacket(
1749 1, kClientDataStreamId1, true, true,
1750 GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
1751 quic_data.AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
1752 kDefaultMaxUncompressedHeaderSize,
1753 &header_stream_offset));
1754 // Peer sending data from an non-existing stream causes this end to raise
1755 // error and close connection.
1756 quic_data.AddRead(
1757 ConstructServerRstPacket(1, false, 99, QUIC_STREAM_LAST_ERROR));
1758 std::string quic_error_details = "Data for nonexistent stream";
1759 quic_data.AddWrite(ConstructClientAckAndConnectionClosePacket(
1760 3, QuicTime::Delta::Zero(), 1, 1, QUIC_INVALID_STREAM_ID,
1761 quic_error_details));
1762 quic_data.AddSocketDataToFactory(&socket_factory_);
1763
1764 // In order for a new QUIC session to be established via alternate-protocol
1765 // without racing an HTTP connection, we need the host resolution to happen
1766 // synchronously. Of course, even though QUIC *could* perform a 0-RTT
1767 // connection to the the server, in this test we require confirmation
1768 // before encrypting so the HTTP job will still start.
1769 host_resolver_.set_synchronous_mode(true);
1770 host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
1771 "");
1772 HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
1773 AddressList address;
1774 std::unique_ptr<HostResolver::Request> request;
1775 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
1776 &request, net_log_.bound());
1777
1778 CreateSession();
1779
1780 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
1781
1782 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
1783 TestCompletionCallback callback;
1784 int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
1785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1786
1787 // Pump the message loop to get the request started.
1788 base::RunLoop().RunUntilIdle();
1789 // Explicitly confirm the handshake.
1790 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
1791 QuicSession::HANDSHAKE_CONFIRMED);
1792
1793 ASSERT_FALSE(quic_data.AllReadDataConsumed());
1794
1795 // Run the QUIC session to completion.
1796 base::RunLoop().RunUntilIdle();
1797 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
1798 ASSERT_TRUE(quic_data.AllReadDataConsumed());
1799
1800 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_QUIC_PROTOCOL_ERROR));
1801 ExpectQuicAlternateProtocolMapping();
1802 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
1803 }
1804
1742 // Verify that with mark_quic_broken_when_network_blackholes enabled, if a QUIC 1805 // Verify that with mark_quic_broken_when_network_blackholes enabled, if a QUIC
1743 // connection times out, then QUIC will be marked as broken and the request 1806 // connection times out, then QUIC will be marked as broken and the request
1744 // retried over TCP. 1807 // retried over TCP.
1745 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken) { 1808 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken) {
1746 params_.mark_quic_broken_when_network_blackholes = true; 1809 params_.mark_quic_broken_when_network_blackholes = true;
1747 params_.quic_idle_connection_timeout_seconds = 5; 1810 params_.quic_idle_connection_timeout_seconds = 5;
1748 1811
1749 // The request will initially go out over QUIC. 1812 // The request will initially go out over QUIC.
1750 MockQuicData quic_data; 1813 MockQuicData quic_data;
1751 QuicStreamOffset header_stream_offset = 0; 1814 QuicStreamOffset header_stream_offset = 0;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1850 ExpectBrokenAlternateProtocolMapping(); 1913 ExpectBrokenAlternateProtocolMapping();
1851 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); 1914 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
1852 ASSERT_FALSE(http_data.AllReadDataConsumed()); 1915 ASSERT_FALSE(http_data.AllReadDataConsumed());
1853 1916
1854 // Read the response body over TCP. 1917 // Read the response body over TCP.
1855 CheckResponseData(&trans, "hello world"); 1918 CheckResponseData(&trans, "hello world");
1856 ASSERT_TRUE(http_data.AllWriteDataConsumed()); 1919 ASSERT_TRUE(http_data.AllWriteDataConsumed());
1857 ASSERT_TRUE(http_data.AllReadDataConsumed()); 1920 ASSERT_TRUE(http_data.AllReadDataConsumed());
1858 } 1921 }
1859 1922
1923 // Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
1924 // connection times out, then QUIC will be marked as broken and the request
1925 // retried over TCP.
1926 TEST_P(QuicNetworkTransactionTest, TimeoutAfterHandshakeConfirmedThenBroken2) {
1927 params_.retry_without_alt_svc_on_quic_errors = true;
1928 params_.quic_idle_connection_timeout_seconds = 5;
1929
1930 // The request will initially go out over QUIC.
1931 MockQuicData quic_data;
1932 QuicStreamOffset header_stream_offset = 0;
1933 SpdyPriority priority =
1934 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
1935
1936 std::string request_data;
1937 quic_data.AddWrite(client_maker_.MakeRequestHeadersPacketAndSaveData(
1938 1, kClientDataStreamId1, true, true, priority,
1939 GetRequestHeaders("GET", "https", "/"), nullptr, &header_stream_offset,
1940 &request_data));
1941
1942 std::string settings_data;
1943 QuicStreamOffset settings_offset = header_stream_offset;
1944 quic_data.AddWrite(client_maker_.MakeSettingsPacketAndSaveData(
1945 2, SETTINGS_MAX_HEADER_LIST_SIZE, kDefaultMaxUncompressedHeaderSize, true,
1946 &header_stream_offset, &settings_data));
1947 // TLP 1
1948 quic_data.AddWrite(client_maker_.MakeDataPacket(3, kHeadersStreamId, true,
1949 false, 0, request_data));
1950 // TLP 2
1951 quic_data.AddWrite(client_maker_.MakeDataPacket(
1952 4, kHeadersStreamId, true, false, settings_offset, settings_data));
1953 // RTO 1
1954 quic_data.AddWrite(client_maker_.MakeDataPacket(5, kHeadersStreamId, true,
1955 false, 0, request_data));
1956 quic_data.AddWrite(client_maker_.MakeDataPacket(
1957 6, kHeadersStreamId, true, false, settings_offset, settings_data));
1958 // RTO 2
1959 quic_data.AddWrite(client_maker_.MakeDataPacket(7, kHeadersStreamId, true,
1960 false, 0, request_data));
1961 quic_data.AddWrite(client_maker_.MakeDataPacket(
1962 8, kHeadersStreamId, true, false, settings_offset, settings_data));
1963 // RTO 3
1964 quic_data.AddWrite(client_maker_.MakeDataPacket(9, kHeadersStreamId, true,
1965 false, 0, request_data));
1966 quic_data.AddWrite(client_maker_.MakeDataPacket(
1967 10, kHeadersStreamId, true, false, settings_offset, settings_data));
1968
1969 quic_data.AddRead(ASYNC, ERR_IO_PENDING);
1970 quic_data.AddRead(ASYNC, OK);
1971 quic_data.AddSocketDataToFactory(&socket_factory_);
1972
1973 // After that fails, it will be resent via TCP.
1974 MockWrite http_writes[] = {
1975 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
1976 MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"),
1977 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")};
1978
1979 MockRead http_reads[] = {
1980 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
1981 MockRead(SYNCHRONOUS, 4, kQuicAlternativeServiceHeader),
1982 MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)};
1983 SequencedSocketData http_data(http_reads, arraysize(http_reads), http_writes,
1984 arraysize(http_writes));
1985 socket_factory_.AddSocketDataProvider(&http_data);
1986 socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
1987
1988 // In order for a new QUIC session to be established via alternate-protocol
1989 // without racing an HTTP connection, we need the host resolution to happen
1990 // synchronously. Of course, even though QUIC *could* perform a 0-RTT
1991 // connection to the the server, in this test we require confirmation
1992 // before encrypting so the HTTP job will still start.
1993 host_resolver_.set_synchronous_mode(true);
1994 host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
1995 "");
1996 HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
1997 AddressList address;
1998 std::unique_ptr<HostResolver::Request> request;
1999 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
2000 &request, net_log_.bound());
2001
2002 CreateSession();
2003 // Use a TestTaskRunner to avoid waiting in real time for timeouts.
2004 scoped_refptr<TestTaskRunner> quic_task_runner_(new TestTaskRunner(clock_));
2005 QuicStreamFactoryPeer::SetAlarmFactory(
2006 session_->quic_stream_factory(),
2007 base::MakeUnique<QuicChromiumAlarmFactory>(quic_task_runner_.get(),
2008 clock_));
2009
2010 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
2011
2012 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
2013 TestCompletionCallback callback;
2014 int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
2015 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2016
2017 // Pump the message loop to get the request started.
2018 base::RunLoop().RunUntilIdle();
2019 // Explicitly confirm the handshake.
2020 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
2021 QuicSession::HANDSHAKE_CONFIRMED);
2022
2023 // Run the QUIC session to completion.
2024 quic_task_runner_->RunUntilIdle();
2025 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
2026
2027 ExpectQuicAlternateProtocolMapping();
2028
2029 // Let the transaction proceed which will result in QUIC being marked
2030 // as broken and the request falling back to TCP.
2031 EXPECT_THAT(callback.WaitForResult(), IsOk());
2032
2033 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
2034 ASSERT_FALSE(http_data.AllReadDataConsumed());
2035
2036 // Read the response body over TCP.
2037 CheckResponseData(&trans, "hello world");
2038 ExpectBrokenAlternateProtocolMapping();
2039 ASSERT_TRUE(http_data.AllWriteDataConsumed());
2040 ASSERT_TRUE(http_data.AllReadDataConsumed());
2041 }
2042
1860 // Verify that with mark_quic_broken_when_network_blackholes enabled, if a QUIC 2043 // Verify that with mark_quic_broken_when_network_blackholes enabled, if a QUIC
1861 // connection times out, then QUIC will be marked as broken but the request 2044 // connection times out, then QUIC will be marked as broken but the request
1862 // will not be retried over TCP. 2045 // will not be retried over TCP.
1863 TEST_P(QuicNetworkTransactionTest, 2046 TEST_P(QuicNetworkTransactionTest,
1864 TimeoutAfterHandshakeConfirmedAndHeadersThenBrokenNotRetried) { 2047 TimeoutAfterHandshakeConfirmedAndHeadersThenBrokenNotRetried) {
1865 params_.mark_quic_broken_when_network_blackholes = true; 2048 params_.mark_quic_broken_when_network_blackholes = true;
1866 params_.quic_idle_connection_timeout_seconds = 5; 2049 params_.quic_idle_connection_timeout_seconds = 5;
1867 2050
1868 // The request will initially go out over QUIC. 2051 // The request will initially go out over QUIC.
1869 MockQuicData quic_data; 2052 MockQuicData quic_data;
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
2197 trans.reset(); 2380 trans.reset();
2198 2381
2199 // Run the QUIC session to completion. 2382 // Run the QUIC session to completion.
2200 quic_task_runner_->RunUntilIdle(); 2383 quic_task_runner_->RunUntilIdle();
2201 2384
2202 ExpectBrokenAlternateProtocolMapping(); 2385 ExpectBrokenAlternateProtocolMapping();
2203 2386
2204 ASSERT_TRUE(quic_data.AllWriteDataConsumed()); 2387 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
2205 } 2388 }
2206 2389
2390 // Verify that with retry_without_alt_svc_on_quic_errors enabled, if a QUIC
2391 // protocol error occurs after the handshake is confirmed, the request
2392 // retried over TCP and the QUIC will be marked as broken.
2393 TEST_P(QuicNetworkTransactionTest,
2394 ProtocolErrorAfterHandshakeConfirmedThenBroken) {
2395 params_.retry_without_alt_svc_on_quic_errors = true;
2396 params_.quic_idle_connection_timeout_seconds = 5;
2397
2398 // The request will initially go out over QUIC.
2399 MockQuicData quic_data;
2400 QuicStreamOffset header_stream_offset = 0;
2401 quic_data.AddWrite(ConstructClientRequestHeadersPacket(
2402 1, kClientDataStreamId1, true, true,
2403 GetRequestHeaders("GET", "https", "/"), &header_stream_offset));
2404 quic_data.AddWrite(ConstructSettingsPacket(2, SETTINGS_MAX_HEADER_LIST_SIZE,
2405 kDefaultMaxUncompressedHeaderSize,
2406 &header_stream_offset));
2407 // Peer sending data from an non-existing stream causes this end to raise
2408 // error and close connection.
2409 quic_data.AddRead(
2410 ConstructServerRstPacket(1, false, 99, QUIC_STREAM_LAST_ERROR));
2411 std::string quic_error_details = "Data for nonexistent stream";
2412 quic_data.AddWrite(ConstructClientAckAndConnectionClosePacket(
2413 3, QuicTime::Delta::Zero(), 1, 1, QUIC_INVALID_STREAM_ID,
2414 quic_error_details));
2415 quic_data.AddSocketDataToFactory(&socket_factory_);
2416
2417 // After that fails, it will be resent via TCP.
2418 MockWrite http_writes[] = {
2419 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
2420 MockWrite(SYNCHRONOUS, 1, "Host: mail.example.org\r\n"),
2421 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")};
2422
2423 MockRead http_reads[] = {
2424 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
2425 MockRead(SYNCHRONOUS, 4, kQuicAlternativeServiceHeader),
2426 MockRead(SYNCHRONOUS, 5, "hello world"), MockRead(SYNCHRONOUS, OK, 6)};
2427 SequencedSocketData http_data(http_reads, arraysize(http_reads), http_writes,
2428 arraysize(http_writes));
2429 socket_factory_.AddSocketDataProvider(&http_data);
2430 socket_factory_.AddSSLSocketDataProvider(&ssl_data_);
2431
2432 // In order for a new QUIC session to be established via alternate-protocol
2433 // without racing an HTTP connection, we need the host resolution to happen
2434 // synchronously. Of course, even though QUIC *could* perform a 0-RTT
2435 // connection to the the server, in this test we require confirmation
2436 // before encrypting so the HTTP job will still start.
2437 host_resolver_.set_synchronous_mode(true);
2438 host_resolver_.rules()->AddIPLiteralRule("mail.example.org", "192.168.0.1",
2439 "");
2440 HostResolver::RequestInfo info(HostPortPair("mail.example.org", 443));
2441 AddressList address;
2442 std::unique_ptr<HostResolver::Request> request;
2443 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, CompletionCallback(),
2444 &request, net_log_.bound());
2445
2446 CreateSession();
2447
2448 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
2449
2450 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
2451 TestCompletionCallback callback;
2452 int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
2453 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2454
2455 // Pump the message loop to get the request started.
2456 base::RunLoop().RunUntilIdle();
2457 // Explicitly confirm the handshake.
2458 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
2459 QuicSession::HANDSHAKE_CONFIRMED);
2460
2461 // Run the QUIC session to completion.
2462 base::RunLoop().RunUntilIdle();
2463 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
2464
2465 ExpectQuicAlternateProtocolMapping();
2466
2467 // Let the transaction proceed which will result in QUIC being marked
2468 // as broken and the request falling back to TCP.
2469 EXPECT_THAT(callback.WaitForResult(), IsOk());
2470
2471 ASSERT_TRUE(quic_data.AllWriteDataConsumed());
2472 ASSERT_FALSE(http_data.AllReadDataConsumed());
2473
2474 // Read the response body over TCP.
2475 CheckResponseData(&trans, "hello world");
2476 ExpectBrokenAlternateProtocolMapping();
2477 ASSERT_TRUE(http_data.AllWriteDataConsumed());
2478 ASSERT_TRUE(http_data.AllReadDataConsumed());
2479 }
2480
2207 TEST_P(QuicNetworkTransactionTest, 2481 TEST_P(QuicNetworkTransactionTest,
2208 DoNotUseAlternativeServiceQuicUnsupportedVersion) { 2482 DoNotUseAlternativeServiceQuicUnsupportedVersion) {
2209 std::string altsvc_header = base::StringPrintf( 2483 std::string altsvc_header = base::StringPrintf(
2210 "Alt-Svc: quic=\":443\"; v=\"%u\"\r\n\r\n", version_ - 1); 2484 "Alt-Svc: quic=\":443\"; v=\"%u\"\r\n\r\n", version_ - 1);
2211 MockRead http_reads[] = { 2485 MockRead http_reads[] = {
2212 MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()), 2486 MockRead("HTTP/1.1 200 OK\r\n"), MockRead(altsvc_header.c_str()),
2213 MockRead("hello world"), 2487 MockRead("hello world"),
2214 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), 2488 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2215 MockRead(ASYNC, OK)}; 2489 MockRead(ASYNC, OK)};
2216 2490
(...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after
4436 4710
4437 request_.url = GURL("https://mail.example.org/pushed.jpg"); 4711 request_.url = GURL("https://mail.example.org/pushed.jpg");
4438 ChunkedUploadDataStream upload_data(0); 4712 ChunkedUploadDataStream upload_data(0);
4439 upload_data.AppendData("1", 1, true); 4713 upload_data.AppendData("1", 1, true);
4440 request_.upload_data_stream = &upload_data; 4714 request_.upload_data_stream = &upload_data;
4441 SendRequestAndExpectQuicResponse("and hello!"); 4715 SendRequestAndExpectQuicResponse("and hello!");
4442 } 4716 }
4443 4717
4444 } // namespace test 4718 } // namespace test
4445 } // namespace net 4719 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_network_transaction.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698