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

Side by Side Diff: net/spdy/spdy_session_spdy3_unittest.cc

Issue 13834009: SPDY - Re-land greedy read support for SpdySession (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: histograms to track bytes_read during init Created 7 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 | Annotate | Revision Log
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 "net/spdy/spdy_session.h" 5 #include "net/spdy/spdy_session.h"
6 6
7 #include "base/memory/scoped_ptr.h"
8 #include "net/base/io_buffer.h"
7 #include "net/base/ip_endpoint.h" 9 #include "net/base/ip_endpoint.h"
8 #include "net/base/net_log_unittest.h" 10 #include "net/base/net_log_unittest.h"
9 #include "net/base/request_priority.h" 11 #include "net/base/request_priority.h"
10 #include "net/base/test_data_directory.h" 12 #include "net/base/test_data_directory.h"
13 #include "net/base/test_data_stream.h"
11 #include "net/dns/host_cache.h" 14 #include "net/dns/host_cache.h"
12 #include "net/spdy/spdy_http_utils.h" 15 #include "net/spdy/spdy_http_utils.h"
13 #include "net/spdy/spdy_io_buffer.h" 16 #include "net/spdy/spdy_io_buffer.h"
14 #include "net/spdy/spdy_session_pool.h" 17 #include "net/spdy/spdy_session_pool.h"
18 #include "net/spdy/spdy_session_test_util.h"
15 #include "net/spdy/spdy_stream.h" 19 #include "net/spdy/spdy_stream.h"
16 #include "net/spdy/spdy_stream_test_util.h" 20 #include "net/spdy/spdy_stream_test_util.h"
17 #include "net/spdy/spdy_test_util_common.h" 21 #include "net/spdy/spdy_test_util_common.h"
18 #include "net/spdy/spdy_test_util_spdy3.h" 22 #include "net/spdy/spdy_test_util_spdy3.h"
19 #include "net/test/cert_test_util.h" 23 #include "net/test/cert_test_util.h"
20 #include "testing/platform_test.h" 24 #include "testing/platform_test.h"
21 25
22 using namespace net::test_spdy3; 26 using namespace net::test_spdy3;
23 27
24 namespace net { 28 namespace net {
(...skipping 1653 matching lines...) Expand 10 before | Expand all | Expand 10 after
1678 spdy_stream1 = NULL; 1682 spdy_stream1 = NULL;
1679 1683
1680 scoped_refptr<SpdyStream> spdy_stream2 = 1684 scoped_refptr<SpdyStream> spdy_stream2 =
1681 CreateStreamSynchronously(session, test_url_, MEDIUM, BoundNetLog()); 1685 CreateStreamSynchronously(session, test_url_, MEDIUM, BoundNetLog());
1682 ASSERT_TRUE(spdy_stream2.get() != NULL); 1686 ASSERT_TRUE(spdy_stream2.get() != NULL);
1683 EXPECT_EQ(spdy_stream2->send_window_size(), window_size); 1687 EXPECT_EQ(spdy_stream2->send_window_size(), window_size);
1684 spdy_stream2->Cancel(); 1688 spdy_stream2->Cancel();
1685 spdy_stream2 = NULL; 1689 spdy_stream2 = NULL;
1686 } 1690 }
1687 1691
1692 // Test that SpdySession::DoRead reads data from the socket without yielding.
1693 // This test makes 32k - 1 bytes of data available on the socket for reading. It
1694 // then verifies that it has read all the available data without yielding.
1695 TEST_F(SpdySessionSpdy3Test, ReadDataWithoutYielding) {
1696 MockConnect connect_data(SYNCHRONOUS, OK);
1697 BufferedSpdyFramer framer(3, false);
1698
1699 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
1700 MockWrite writes[] = {
1701 CreateMockWrite(*req1, 0),
1702 };
1703
1704 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1705 ASSERT_EQ(32 * 1024, kMaxReadBytes);
1706 const int kPayloadSize =
1707 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
1708 TestDataStream test_stream;
1709 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
1710 char* payload_data = payload->data();
1711 test_stream.GetBytes(payload_data, kPayloadSize);
1712
1713 scoped_ptr<SpdyFrame> partial_data_frame(
1714 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
1715 scoped_ptr<SpdyFrame> finish_data_frame(
1716 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
1717
1718 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
1719
1720 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
1721 // bytes.
1722 MockRead reads[] = {
1723 CreateMockRead(*resp1, 1),
1724 CreateMockRead(*partial_data_frame, 2),
1725 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
1726 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
1727 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
1728 MockRead(ASYNC, 0, 6) // EOF
1729 };
1730
1731 // Create SpdySession and SpdyStream and send the request.
1732 DeterministicSocketData data(reads, arraysize(reads),
1733 writes, arraysize(writes));
1734 data.set_connect_data(connect_data);
1735 session_deps_.host_resolver->set_synchronous_mode(true);
1736 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1737
1738 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1739 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1740
1741 CreateDeterministicNetworkSession();
1742
1743 scoped_refptr<SpdySession> session = CreateInitializedSession();
1744
1745 GURL url1("http://www.google.com");
1746 scoped_refptr<SpdyStream> spdy_stream1 =
1747 CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
1748 ASSERT_TRUE(spdy_stream1.get() != NULL);
1749 EXPECT_EQ(0u, spdy_stream1->stream_id());
1750
1751 spdy_stream1->set_spdy_headers(ConstructGetHeaderBlock(url1.spec()));
1752 EXPECT_TRUE(spdy_stream1->HasUrl());
1753 spdy_stream1->SendRequest(false);
1754
1755 // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task.
1756 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
1757
1758 // Run until 1st read.
1759 EXPECT_EQ(0u, spdy_stream1->stream_id());
1760 data.RunFor(2);
1761 EXPECT_EQ(1u, spdy_stream1->stream_id());
1762 EXPECT_EQ(0u, observer.executed_count());
1763
1764 // Read all the data and verify SpdySession::DoRead has not posted a task.
1765 data.RunFor(4);
1766
1767 // Verify task observer's executed_count is zero, which indicates DoRead read
1768 // all the available data.
1769 EXPECT_EQ(0u, observer.executed_count());
1770 EXPECT_TRUE(data.at_write_eof());
1771 EXPECT_TRUE(data.at_read_eof());
1772 }
1773
1774 // Test that SpdySession::DoRead yields while reading the data. This test makes
1775 // 32k + 1 bytes of data available on the socket for reading. It then verifies
1776 // that DoRead has yielded even though there is data available for it to read
1777 // (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads).
1778 TEST_F(SpdySessionSpdy3Test, TestYieldingDuringReadData) {
1779 MockConnect connect_data(SYNCHRONOUS, OK);
1780 BufferedSpdyFramer framer(3, false);
1781
1782 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
1783 MockWrite writes[] = {
1784 CreateMockWrite(*req1, 0),
1785 };
1786
1787 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1788 ASSERT_EQ(32 * 1024, kMaxReadBytes);
1789 const int kPayloadSize =
1790 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
1791 TestDataStream test_stream;
1792 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
1793 char* payload_data = payload->data();
1794 test_stream.GetBytes(payload_data, kPayloadSize);
1795
1796 scoped_ptr<SpdyFrame> partial_data_frame(
1797 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
1798 scoped_ptr<SpdyFrame> finish_data_frame(
1799 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
1800
1801 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
1802
1803 // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
1804 MockRead reads[] = {
1805 CreateMockRead(*resp1, 1),
1806 CreateMockRead(*partial_data_frame, 2),
1807 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
1808 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
1809 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
1810 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
1811 MockRead(ASYNC, 0, 7) // EOF
1812 };
1813
1814 // Create SpdySession and SpdyStream and send the request.
1815 DeterministicSocketData data(reads, arraysize(reads),
1816 writes, arraysize(writes));
1817 data.set_connect_data(connect_data);
1818 session_deps_.host_resolver->set_synchronous_mode(true);
1819 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1820
1821 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1822 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1823
1824 CreateDeterministicNetworkSession();
1825
1826 scoped_refptr<SpdySession> session = CreateInitializedSession();
1827
1828 GURL url1("http://www.google.com");
1829 scoped_refptr<SpdyStream> spdy_stream1 =
1830 CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
1831 ASSERT_TRUE(spdy_stream1.get() != NULL);
1832 EXPECT_EQ(0u, spdy_stream1->stream_id());
1833
1834 spdy_stream1->set_spdy_headers(ConstructGetHeaderBlock(url1.spec()));
1835 EXPECT_TRUE(spdy_stream1->HasUrl());
1836 spdy_stream1->SendRequest(false);
1837
1838 // Set up the TaskObserver to verify SpdySession::DoRead posts a task.
1839 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
1840
1841 // Run until 1st read.
1842 EXPECT_EQ(0u, spdy_stream1->stream_id());
1843 data.RunFor(2);
1844 EXPECT_EQ(1u, spdy_stream1->stream_id());
1845 EXPECT_EQ(0u, observer.executed_count());
1846
1847 // Read all the data and verify SpdySession::DoRead has posted a task.
1848 data.RunFor(6);
1849
1850 // Verify task observer's executed_count is 1, which indicates DoRead has
1851 // posted only one task and thus yielded though there is data available for it
1852 // to read.
1853 EXPECT_EQ(1u, observer.executed_count());
1854 EXPECT_TRUE(data.at_write_eof());
1855 EXPECT_TRUE(data.at_read_eof());
1856 }
1857
1858 // Test that SpdySession::DoRead() tests interactions of yielding + async,
1859 // by doing the following MockReads.
1860 //
1861 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
1862 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
1863 //
1864 // The above reads 26K synchronously. Since that is less that 32K, we will
1865 // attempt to read again. However, that DoRead() will return ERR_IO_PENDING
1866 // (because of async read), so DoRead() will yield. When we come back, DoRead()
1867 // will read the results from the async read, and rest of the data
1868 // synchronously.
1869 TEST_F(SpdySessionSpdy3Test, TestYieldingDuringAsyncReadData) {
1870 MockConnect connect_data(SYNCHRONOUS, OK);
1871 BufferedSpdyFramer framer(3, false);
1872
1873 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
1874 MockWrite writes[] = {
1875 CreateMockWrite(*req1, 0),
1876 };
1877
1878 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1879 ASSERT_EQ(32 * 1024, kMaxReadBytes);
1880 TestDataStream test_stream;
1881 const int kEightKPayloadSize =
1882 kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
1883 scoped_refptr<net::IOBuffer> eightk_payload(
1884 new net::IOBuffer(kEightKPayloadSize));
1885 char* eightk_payload_data = eightk_payload->data();
1886 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
1887
1888 // Build buffer of 2k size.
1889 TestDataStream test_stream2;
1890 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
1891 scoped_refptr<net::IOBuffer> twok_payload(
1892 new net::IOBuffer(kTwoKPayloadSize));
1893 char* twok_payload_data = twok_payload->data();
1894 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
1895
1896 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
1897 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
1898 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
1899 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
1900 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
1901 1, "h", 1, DATA_FLAG_FIN));
1902
1903 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
1904
1905 MockRead reads[] = {
1906 CreateMockRead(*resp1, 1),
1907 CreateMockRead(*eightk_data_frame, 2),
1908 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
1909 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
1910 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
1911 CreateMockRead(*eightk_data_frame, 6, ASYNC),
1912 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
1913 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
1914 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
1915 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
1916 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
1917 MockRead(ASYNC, 0, 12) // EOF
1918 };
1919
1920 // Create SpdySession and SpdyStream and send the request.
1921 DeterministicSocketData data(reads, arraysize(reads),
1922 writes, arraysize(writes));
1923 data.set_connect_data(connect_data);
1924 session_deps_.host_resolver->set_synchronous_mode(true);
1925 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1926
1927 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1928 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1929
1930 CreateDeterministicNetworkSession();
1931
1932 scoped_refptr<SpdySession> session = CreateInitializedSession();
1933
1934 GURL url1("http://www.google.com");
1935 scoped_refptr<SpdyStream> spdy_stream1 =
1936 CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
1937 ASSERT_TRUE(spdy_stream1.get() != NULL);
1938 EXPECT_EQ(0u, spdy_stream1->stream_id());
1939
1940 spdy_stream1->set_spdy_headers(ConstructGetHeaderBlock(url1.spec()));
1941 EXPECT_TRUE(spdy_stream1->HasUrl());
1942 spdy_stream1->SendRequest(false);
1943
1944 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks.
1945 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
1946
1947 // Run until 1st read.
1948 EXPECT_EQ(0u, spdy_stream1->stream_id());
1949 data.RunFor(2);
1950 EXPECT_EQ(1u, spdy_stream1->stream_id());
1951 EXPECT_EQ(0u, observer.executed_count());
1952
1953 // Read all the data and verify SpdySession::DoRead has posted a task.
1954 data.RunFor(12);
1955
1956 // Verify task observer's executed_count is 1, which indicates DoRead has
1957 // posted only one task and thus yielded though there is data available for
1958 // it to read.
1959 EXPECT_EQ(1u, observer.executed_count());
1960 EXPECT_TRUE(data.at_write_eof());
1961 EXPECT_TRUE(data.at_read_eof());
1962 }
1963
1964 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to
1965 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because
1966 // GoAway could delete the SpdySession from the SpdySessionPool and the last
1967 // reference to SpdySession.
1968 TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) {
1969 MockConnect connect_data(SYNCHRONOUS, OK);
1970 BufferedSpdyFramer framer(3, false);
1971
1972 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
1973 MockWrite writes[] = {
1974 CreateMockWrite(*req1, 0),
1975 };
1976
1977 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
1978 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true));
1979 scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway());
1980
1981 MockRead reads[] = {
1982 CreateMockRead(*resp1, 1),
1983 CreateMockRead(*body1, 2),
1984 CreateMockRead(*goaway, 3),
1985 MockRead(ASYNC, 0, 4) // EOF
1986 };
1987
1988 // Create SpdySession and SpdyStream and send the request.
1989 DeterministicSocketData data(reads, arraysize(reads),
1990 writes, arraysize(writes));
1991 data.set_connect_data(connect_data);
1992 session_deps_.host_resolver->set_synchronous_mode(true);
1993 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
1994
1995 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
1996 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
1997
1998 CreateDeterministicNetworkSession();
1999
2000 scoped_refptr<SpdySession> session = CreateInitializedSession();
2001
2002 GURL url1("http://www.google.com");
2003 scoped_refptr<SpdyStream> spdy_stream1 =
2004 CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
2005 ASSERT_TRUE(spdy_stream1.get() != NULL);
2006 EXPECT_EQ(0u, spdy_stream1->stream_id());
2007
2008 spdy_stream1->set_spdy_headers(ConstructGetHeaderBlock(url1.spec()));
2009 EXPECT_TRUE(spdy_stream1->HasUrl());
2010 spdy_stream1->SendRequest(false);
2011
2012 // Run until 1st read.
2013 EXPECT_EQ(0u, spdy_stream1->stream_id());
2014 data.RunFor(1);
2015 EXPECT_EQ(1u, spdy_stream1->stream_id());
2016
2017 // Drop the reference to the session.
2018 session = NULL;
2019
2020 // Run until GoAway.
2021 data.RunFor(2);
2022
2023 // Drop the reference to the stream which deletes its reference to the
2024 // SpdySession. Only references to SpdySession are held by DoLoop and
2025 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if
2026 // SpdySession is deleted from the SpdySessionPool.
2027 spdy_stream1 = NULL;
2028
2029 data.RunFor(2);
2030 EXPECT_TRUE(data.at_write_eof());
2031 EXPECT_TRUE(data.at_read_eof());
2032 }
2033
1688 // Within this framework, a SpdySession should be initialized with 2034 // Within this framework, a SpdySession should be initialized with
1689 // flow control enabled only for streams and with protocol version 3 2035 // flow control enabled only for streams and with protocol version 3
1690 // by default. 2036 // by default.
1691 TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation) { 2037 TEST_F(SpdySessionSpdy3Test, ProtocolNegotiation) {
1692 session_deps_.host_resolver->set_synchronous_mode(true); 2038 session_deps_.host_resolver->set_synchronous_mode(true);
1693 2039
1694 MockConnect connect_data(SYNCHRONOUS, OK); 2040 MockConnect connect_data(SYNCHRONOUS, OK);
1695 MockRead reads[] = { 2041 MockRead reads[] = {
1696 MockRead(SYNCHRONOUS, 0, 0) // EOF 2042 MockRead(SYNCHRONOUS, 0, 0) // EOF
1697 }; 2043 };
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after
2661 EXPECT_EQ(0, delegate1.body_data_sent()); 3007 EXPECT_EQ(0, delegate1.body_data_sent());
2662 3008
2663 EXPECT_TRUE(delegate2.send_headers_completed()); 3009 EXPECT_TRUE(delegate2.send_headers_completed());
2664 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); 3010 EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status"));
2665 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); 3011 EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version"));
2666 EXPECT_EQ("", delegate2.received_data()); 3012 EXPECT_EQ("", delegate2.received_data());
2667 EXPECT_EQ(0, delegate2.body_data_sent()); 3013 EXPECT_EQ(0, delegate2.body_data_sent());
2668 } 3014 }
2669 3015
2670 } // namespace net 3016 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698