Chromium Code Reviews| 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 |