OLD | NEW |
---|---|
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" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/memory/scoped_vector.h" | 8 #include "base/memory/scoped_vector.h" |
9 #include "net/base/cert_test_util.h" | 9 #include "net/base/cert_test_util.h" |
10 #include "net/base/host_cache.h" | 10 #include "net/base/host_cache.h" |
(...skipping 1789 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1800 data.RunFor(6); | 1800 data.RunFor(6); |
1801 | 1801 |
1802 // Verify task observer's executed_count is 1, which indicates DoRead has | 1802 // Verify task observer's executed_count is 1, which indicates DoRead has |
1803 // posted only one task and thus yielded though there is data available for it | 1803 // posted only one task and thus yielded though there is data available for it |
1804 // to read. | 1804 // to read. |
1805 EXPECT_EQ(1u, observer.executed_count()); | 1805 EXPECT_EQ(1u, observer.executed_count()); |
1806 EXPECT_TRUE(data.at_write_eof()); | 1806 EXPECT_TRUE(data.at_write_eof()); |
1807 EXPECT_TRUE(data.at_read_eof()); | 1807 EXPECT_TRUE(data.at_read_eof()); |
1808 } | 1808 } |
1809 | 1809 |
1810 // Test that SpdySession::DoRead yields while reading the data. This test makes | 1810 // Test that SpdySession::DoRead() tests interactions of yielding + async, |
1811 // 4 reads of kMaxReadBytes / 4 (-spdy_data_frame_size), one read of | 1811 // by doing the following MockReads. |
1812 // kMaxReadBytes (-spdy_data_frame_size), and some reads of kMaxReadBytes + 8k | 1812 // |
1813 // (-spdy_data_frame_size), bytes of data available on the socket for reading. | 1813 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K |
1814 // It then verifies that DoRead has yielded even though there is data available | 1814 // ASYNC 6K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K. |
1815 // for it to read (i.e, socket()->Read didn't return ERR_IO_PENDING during | 1815 // |
1816 // socket reads). Also verifies that SpdySession reads only | 1816 // The above reads 26K synchronously. Since that is less that 32K, we will |
1817 // SpdySession::kReadBufferSize data from the underlying transport. | 1817 // attempt to read again. However, that DoRead() will return ERR_IO_PENDING |
1818 // TODO(rtennti): Make this test work after fixes to DeterministicSocketData. | 1818 // (because of async read), so DoRead() will yield. When we come back, DoRead() |
1819 TEST_F(SpdySessionSpdy2Test, DISABLED_TestYieldingDuringLargeReadData) { | 1819 // will read the results from the async read, and rest of the data |
1820 // synchronously. | |
1821 TEST_F(SpdySessionSpdy2Test, TestYieldingDuringAsyncReadData) { | |
1820 MockConnect connect_data(SYNCHRONOUS, OK); | 1822 MockConnect connect_data(SYNCHRONOUS, OK); |
1821 BufferedSpdyFramer framer(2, false); | 1823 BufferedSpdyFramer framer(2, false); |
1822 | 1824 |
1823 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); | 1825 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
1824 MockWrite writes[] = { | 1826 MockWrite writes[] = { |
1825 CreateMockWrite(*req1, 0), | 1827 CreateMockWrite(*req1, 0), |
1826 }; | 1828 }; |
1827 | 1829 |
1828 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). | 1830 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). |
1829 ASSERT_EQ(32 * 1024, kMaxReadBytes); | 1831 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
1830 TestDataStream test_stream; | 1832 TestDataStream test_stream; |
1831 const int kSmallPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); | 1833 const int kEightKPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
1832 scoped_refptr<net::IOBuffer> small_payload( | 1834 scoped_refptr<net::IOBuffer> eightk_payload( |
1833 new net::IOBuffer(kSmallPayloadSize)); | 1835 new net::IOBuffer(kEightKPayloadSize)); |
1834 char* small_payload_data = small_payload->data(); | 1836 char* eightk_payload_data = eightk_payload->data(); |
1835 test_stream.GetBytes(small_payload_data, kSmallPayloadSize); | 1837 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); |
1836 | 1838 |
1837 // Build buffer of size kMaxReadBytes - (-spdy_data_frame_size). | 1839 // Build buffer of 6k size. |
1838 TestDataStream test_stream1; | 1840 TestDataStream test_stream1; |
1839 const int kMaxReadBytesPayloadSize = kMaxReadBytes - SpdyDataFrame::size(); | 1841 const int kSixKPayloadSize = kEightKPayloadSize - 2 * 1024; |
1840 scoped_refptr<net::IOBuffer> max_bytes_payload( | 1842 scoped_refptr<net::IOBuffer> sixk_bytes_payload( |
1841 new net::IOBuffer(kMaxReadBytesPayloadSize)); | 1843 new net::IOBuffer(kSixKPayloadSize)); |
1842 char* max_bytes_payload_data = max_bytes_payload->data(); | 1844 char* sixk_bytes_payload_data = sixk_bytes_payload->data(); |
1843 test_stream1.GetBytes(max_bytes_payload_data, kMaxReadBytesPayloadSize); | 1845 test_stream1.GetBytes(sixk_bytes_payload_data, kSixKPayloadSize); |
1844 | 1846 |
1845 // Build buffer of size kMaxReadBytes + kSmallPayloadSize | 1847 // Build buffer of 2k size. |
1846 // (-spdy_data_frame_size). | |
1847 TestDataStream test_stream2; | 1848 TestDataStream test_stream2; |
1848 const int kLargePayloadSize = | 1849 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; |
1849 kMaxReadBytes + kSmallPayloadSize - SpdyDataFrame::size(); | 1850 scoped_refptr<net::IOBuffer> twok_payload( |
1850 scoped_refptr<net::IOBuffer> large_payload( | 1851 new net::IOBuffer(kTwoKPayloadSize)); |
1851 new net::IOBuffer(kLargePayloadSize)); | 1852 char* twok_payload_data = twok_payload->data(); |
1852 char* large_payload_data = large_payload->data(); | 1853 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); |
1853 test_stream2.GetBytes(large_payload_data, kLargePayloadSize); | |
1854 | 1854 |
1855 scoped_ptr<SpdyFrame> small_data_frame(framer.CreateDataFrame( | 1855 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( |
1856 1, small_payload_data, kSmallPayloadSize, DATA_FLAG_NONE)); | 1856 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); |
1857 scoped_ptr<SpdyFrame> max_bytes_data_frame(framer.CreateDataFrame( | 1857 scoped_ptr<SpdyFrame> sixk_bytes_data_frame(framer.CreateDataFrame( |
1858 1, max_bytes_payload_data, kMaxReadBytesPayloadSize, DATA_FLAG_NONE)); | 1858 1, sixk_bytes_payload_data, kSixKPayloadSize, DATA_FLAG_NONE)); |
1859 scoped_ptr<SpdyFrame> large_data_frame(framer.CreateDataFrame( | 1859 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( |
1860 1, large_payload_data, kLargePayloadSize, DATA_FLAG_NONE)); | 1860 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); |
1861 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( | 1861 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( |
1862 1, "h", 1, DATA_FLAG_FIN)); | 1862 1, "h", 1, DATA_FLAG_FIN)); |
1863 | 1863 |
1864 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); | 1864 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
1865 | 1865 |
1866 MockRead reads[] = { | 1866 MockRead reads[] = { |
1867 CreateMockRead(*resp1, 1), | 1867 CreateMockRead(*resp1, 1), |
1868 CreateMockRead(*small_data_frame, 2), | 1868 CreateMockRead(*eightk_data_frame, 2), |
1869 CreateMockRead(*small_data_frame, 3, SYNCHRONOUS), | 1869 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), |
1870 CreateMockRead(*small_data_frame, 4, SYNCHRONOUS), | 1870 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), |
1871 CreateMockRead(*small_data_frame, 5, SYNCHRONOUS), | 1871 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), |
1872 CreateMockRead(*max_bytes_data_frame, 6), | 1872 CreateMockRead(*sixk_bytes_data_frame, 6, ASYNC), |
Ryan Hamilton
2013/02/12 18:35:39
Can you make this return 8K?
ramant (doing other things)
2013/02/12 18:44:43
Done.
| |
1873 CreateMockRead(*large_data_frame, 7, SYNCHRONOUS), | 1873 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), |
1874 CreateMockRead(*finish_data_frame, 8, SYNCHRONOUS), | 1874 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), |
1875 MockRead(ASYNC, 0, 9) // EOF | 1875 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), |
1876 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), | |
1877 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), | |
1878 MockRead(ASYNC, 0, 12) // EOF | |
1876 }; | 1879 }; |
1877 | 1880 |
1878 // Create SpdySession and SpdyStream and send the request. | 1881 // Create SpdySession and SpdyStream and send the request. |
1879 DeterministicSocketData data(reads, arraysize(reads), | 1882 DeterministicSocketData data(reads, arraysize(reads), |
1880 writes, arraysize(writes)); | 1883 writes, arraysize(writes)); |
1881 data.set_connect_data(connect_data); | 1884 data.set_connect_data(connect_data); |
1882 session_deps_.host_resolver->set_synchronous_mode(true); | 1885 session_deps_.host_resolver->set_synchronous_mode(true); |
1883 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | 1886 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
1884 | 1887 |
1885 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | 1888 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
(...skipping 14 matching lines...) Expand all Loading... | |
1900 (*headers)["method"] = "GET"; | 1903 (*headers)["method"] = "GET"; |
1901 (*headers)["scheme"] = url1.scheme(); | 1904 (*headers)["scheme"] = url1.scheme(); |
1902 (*headers)["host"] = url1.host(); | 1905 (*headers)["host"] = url1.host(); |
1903 (*headers)["url"] = url1.path(); | 1906 (*headers)["url"] = url1.path(); |
1904 (*headers)["version"] = "HTTP/1.1"; | 1907 (*headers)["version"] = "HTTP/1.1"; |
1905 | 1908 |
1906 spdy_stream1->set_spdy_headers(headers.Pass()); | 1909 spdy_stream1->set_spdy_headers(headers.Pass()); |
1907 EXPECT_TRUE(spdy_stream1->HasUrl()); | 1910 EXPECT_TRUE(spdy_stream1->HasUrl()); |
1908 spdy_stream1->SendRequest(false); | 1911 spdy_stream1->SendRequest(false); |
1909 | 1912 |
1910 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. | 1913 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks. |
1911 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); | 1914 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
1912 | 1915 |
1913 // Run until 1st read. | 1916 // Run until 1st read. |
1914 EXPECT_EQ(0u, spdy_stream1->stream_id()); | 1917 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
1915 data.RunFor(2); | 1918 data.RunFor(2); |
1916 EXPECT_EQ(1u, spdy_stream1->stream_id()); | 1919 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
1917 EXPECT_EQ(0u, observer.executed_count()); | 1920 EXPECT_EQ(0u, observer.executed_count()); |
1918 | 1921 |
1919 // Read all the data and verify SpdySession::DoRead has posted a task. | 1922 // Read all the data and verify SpdySession::DoRead has posted a task. |
1920 data.RunFor(10); | 1923 data.RunFor(12); |
1921 | 1924 |
1922 // Verify task observer's executed_count is 1, which indicates DoRead has | 1925 // Verify task observer's executed_count is 1, which indicates DoRead has |
1923 // posted only one task and thus yielded though there is data available for | 1926 // posted only one task and thus yielded though there is data available for |
1924 // it to read. | 1927 // it to read. |
1925 EXPECT_EQ(1u, observer.executed_count()); | 1928 EXPECT_EQ(1u, observer.executed_count()); |
1926 EXPECT_TRUE(data.at_write_eof()); | 1929 EXPECT_TRUE(data.at_write_eof()); |
1927 EXPECT_TRUE(data.at_read_eof()); | 1930 EXPECT_TRUE(data.at_read_eof()); |
1928 } | 1931 } |
1929 | 1932 |
1933 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to | |
1934 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because | |
1935 // GoAway could delete the SpdySession from the SpdySessionPool and the last | |
1936 // reference to SpdySession. | |
1937 TEST_F(SpdySessionSpdy2Test, GoAwayWhileInDoLoop) { | |
1938 MockConnect connect_data(SYNCHRONOUS, OK); | |
1939 BufferedSpdyFramer framer(2, false); | |
1940 | |
1941 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); | |
1942 MockWrite writes[] = { | |
1943 CreateMockWrite(*req1, 0), | |
1944 }; | |
1945 | |
1946 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); | |
1947 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); | |
1948 scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway()); | |
1949 | |
1950 MockRead reads[] = { | |
1951 CreateMockRead(*resp1, 1), | |
1952 CreateMockRead(*body1, 2), | |
1953 CreateMockRead(*goaway, 3), | |
1954 MockRead(ASYNC, 0, 4) // EOF | |
1955 }; | |
1956 | |
1957 // Create SpdySession and SpdyStream and send the request. | |
1958 DeterministicSocketData data(reads, arraysize(reads), | |
1959 writes, arraysize(writes)); | |
1960 data.set_connect_data(connect_data); | |
1961 session_deps_.host_resolver->set_synchronous_mode(true); | |
1962 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | |
1963 | |
1964 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
1965 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); | |
1966 | |
1967 CreateDeterministicNetworkSession(); | |
1968 | |
1969 scoped_refptr<SpdySession> session = CreateInitializedSession(); | |
1970 | |
1971 scoped_refptr<SpdyStream> spdy_stream1; | |
1972 TestCompletionCallback callback1; | |
1973 GURL url1("http://www.google.com"); | |
1974 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, | |
1975 BoundNetLog(), callback1.callback())); | |
1976 EXPECT_EQ(0u, spdy_stream1->stream_id()); | |
1977 | |
1978 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); | |
1979 (*headers)["method"] = "GET"; | |
1980 (*headers)["scheme"] = url1.scheme(); | |
1981 (*headers)["host"] = url1.host(); | |
1982 (*headers)["url"] = url1.path(); | |
1983 (*headers)["version"] = "HTTP/1.1"; | |
1984 | |
1985 spdy_stream1->set_spdy_headers(headers.Pass()); | |
1986 EXPECT_TRUE(spdy_stream1->HasUrl()); | |
1987 spdy_stream1->SendRequest(false); | |
1988 | |
1989 // Run until 1st read. | |
1990 EXPECT_EQ(0u, spdy_stream1->stream_id()); | |
1991 data.RunFor(1); | |
1992 EXPECT_EQ(1u, spdy_stream1->stream_id()); | |
1993 | |
1994 // Drop the reference to the session. | |
1995 session = NULL; | |
1996 | |
1997 // Run until GoAway. | |
1998 data.RunFor(2); | |
1999 | |
2000 // Drop the reference to the stream which deletes its reference to the | |
2001 // SpdySession. Only references to SpdySession are held by DoLoop and | |
2002 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if | |
2003 // SpdySession is deleted from the SpdySessionPool. | |
2004 spdy_stream1 = NULL; | |
2005 | |
2006 data.RunFor(2); | |
2007 EXPECT_TRUE(data.at_write_eof()); | |
2008 EXPECT_TRUE(data.at_read_eof()); | |
2009 } | |
2010 | |
1930 } // namespace net | 2011 } // namespace net |
OLD | NEW |