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 8K, 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 2k size. |
1838 TestDataStream test_stream1; | 1840 TestDataStream test_stream2; |
1839 const int kMaxReadBytesPayloadSize = kMaxReadBytes - SpdyDataFrame::size(); | 1841 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; |
1840 scoped_refptr<net::IOBuffer> max_bytes_payload( | 1842 scoped_refptr<net::IOBuffer> twok_payload( |
1841 new net::IOBuffer(kMaxReadBytesPayloadSize)); | 1843 new net::IOBuffer(kTwoKPayloadSize)); |
1842 char* max_bytes_payload_data = max_bytes_payload->data(); | 1844 char* twok_payload_data = twok_payload->data(); |
1843 test_stream1.GetBytes(max_bytes_payload_data, kMaxReadBytesPayloadSize); | 1845 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); |
1844 | 1846 |
1845 // Build buffer of size kMaxReadBytes + kSmallPayloadSize | 1847 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( |
1846 // (-spdy_data_frame_size). | 1848 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); |
1847 TestDataStream test_stream2; | 1849 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( |
1848 const int kLargePayloadSize = | 1850 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); |
1849 kMaxReadBytes + kSmallPayloadSize - SpdyDataFrame::size(); | |
1850 scoped_refptr<net::IOBuffer> large_payload( | |
1851 new net::IOBuffer(kLargePayloadSize)); | |
1852 char* large_payload_data = large_payload->data(); | |
1853 test_stream2.GetBytes(large_payload_data, kLargePayloadSize); | |
1854 | |
1855 scoped_ptr<SpdyFrame> small_data_frame(framer.CreateDataFrame( | |
1856 1, small_payload_data, kSmallPayloadSize, DATA_FLAG_NONE)); | |
1857 scoped_ptr<SpdyFrame> max_bytes_data_frame(framer.CreateDataFrame( | |
1858 1, max_bytes_payload_data, kMaxReadBytesPayloadSize, DATA_FLAG_NONE)); | |
1859 scoped_ptr<SpdyFrame> large_data_frame(framer.CreateDataFrame( | |
1860 1, large_payload_data, kLargePayloadSize, DATA_FLAG_NONE)); | |
1861 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( | 1851 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( |
1862 1, "h", 1, DATA_FLAG_FIN)); | 1852 1, "h", 1, DATA_FLAG_FIN)); |
1863 | 1853 |
1864 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); | 1854 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
1865 | 1855 |
1866 MockRead reads[] = { | 1856 MockRead reads[] = { |
1867 CreateMockRead(*resp1, 1), | 1857 CreateMockRead(*resp1, 1), |
1868 CreateMockRead(*small_data_frame, 2), | 1858 CreateMockRead(*eightk_data_frame, 2), |
1869 CreateMockRead(*small_data_frame, 3, SYNCHRONOUS), | 1859 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), |
1870 CreateMockRead(*small_data_frame, 4, SYNCHRONOUS), | 1860 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), |
1871 CreateMockRead(*small_data_frame, 5, SYNCHRONOUS), | 1861 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), |
1872 CreateMockRead(*max_bytes_data_frame, 6), | 1862 CreateMockRead(*eightk_data_frame, 6, ASYNC), |
1873 CreateMockRead(*large_data_frame, 7, SYNCHRONOUS), | 1863 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), |
1874 CreateMockRead(*finish_data_frame, 8, SYNCHRONOUS), | 1864 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), |
1875 MockRead(ASYNC, 0, 9) // EOF | 1865 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), |
| 1866 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), |
| 1867 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), |
| 1868 MockRead(ASYNC, 0, 12) // EOF |
1876 }; | 1869 }; |
1877 | 1870 |
1878 // Create SpdySession and SpdyStream and send the request. | 1871 // Create SpdySession and SpdyStream and send the request. |
1879 DeterministicSocketData data(reads, arraysize(reads), | 1872 DeterministicSocketData data(reads, arraysize(reads), |
1880 writes, arraysize(writes)); | 1873 writes, arraysize(writes)); |
1881 data.set_connect_data(connect_data); | 1874 data.set_connect_data(connect_data); |
1882 session_deps_.host_resolver->set_synchronous_mode(true); | 1875 session_deps_.host_resolver->set_synchronous_mode(true); |
1883 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | 1876 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
1884 | 1877 |
1885 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | 1878 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
(...skipping 14 matching lines...) Expand all Loading... |
1900 (*headers)["method"] = "GET"; | 1893 (*headers)["method"] = "GET"; |
1901 (*headers)["scheme"] = url1.scheme(); | 1894 (*headers)["scheme"] = url1.scheme(); |
1902 (*headers)["host"] = url1.host(); | 1895 (*headers)["host"] = url1.host(); |
1903 (*headers)["url"] = url1.path(); | 1896 (*headers)["url"] = url1.path(); |
1904 (*headers)["version"] = "HTTP/1.1"; | 1897 (*headers)["version"] = "HTTP/1.1"; |
1905 | 1898 |
1906 spdy_stream1->set_spdy_headers(headers.Pass()); | 1899 spdy_stream1->set_spdy_headers(headers.Pass()); |
1907 EXPECT_TRUE(spdy_stream1->HasUrl()); | 1900 EXPECT_TRUE(spdy_stream1->HasUrl()); |
1908 spdy_stream1->SendRequest(false); | 1901 spdy_stream1->SendRequest(false); |
1909 | 1902 |
1910 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. | 1903 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks. |
1911 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); | 1904 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
1912 | 1905 |
1913 // Run until 1st read. | 1906 // Run until 1st read. |
1914 EXPECT_EQ(0u, spdy_stream1->stream_id()); | 1907 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
1915 data.RunFor(2); | 1908 data.RunFor(2); |
1916 EXPECT_EQ(1u, spdy_stream1->stream_id()); | 1909 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
1917 EXPECT_EQ(0u, observer.executed_count()); | 1910 EXPECT_EQ(0u, observer.executed_count()); |
1918 | 1911 |
1919 // Read all the data and verify SpdySession::DoRead has posted a task. | 1912 // Read all the data and verify SpdySession::DoRead has posted a task. |
1920 data.RunFor(10); | 1913 data.RunFor(12); |
1921 | 1914 |
1922 // Verify task observer's executed_count is 1, which indicates DoRead has | 1915 // 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 | 1916 // posted only one task and thus yielded though there is data available for |
1924 // it to read. | 1917 // it to read. |
1925 EXPECT_EQ(1u, observer.executed_count()); | 1918 EXPECT_EQ(1u, observer.executed_count()); |
1926 EXPECT_TRUE(data.at_write_eof()); | 1919 EXPECT_TRUE(data.at_write_eof()); |
1927 EXPECT_TRUE(data.at_read_eof()); | 1920 EXPECT_TRUE(data.at_read_eof()); |
1928 } | 1921 } |
1929 | 1922 |
| 1923 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to |
| 1924 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because |
| 1925 // GoAway could delete the SpdySession from the SpdySessionPool and the last |
| 1926 // reference to SpdySession. |
| 1927 TEST_F(SpdySessionSpdy2Test, GoAwayWhileInDoLoop) { |
| 1928 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1929 BufferedSpdyFramer framer(2, false); |
| 1930 |
| 1931 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1932 MockWrite writes[] = { |
| 1933 CreateMockWrite(*req1, 0), |
| 1934 }; |
| 1935 |
| 1936 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1937 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); |
| 1938 scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway()); |
| 1939 |
| 1940 MockRead reads[] = { |
| 1941 CreateMockRead(*resp1, 1), |
| 1942 CreateMockRead(*body1, 2), |
| 1943 CreateMockRead(*goaway, 3), |
| 1944 MockRead(ASYNC, 0, 4) // EOF |
| 1945 }; |
| 1946 |
| 1947 // Create SpdySession and SpdyStream and send the request. |
| 1948 DeterministicSocketData data(reads, arraysize(reads), |
| 1949 writes, arraysize(writes)); |
| 1950 data.set_connect_data(connect_data); |
| 1951 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1952 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1953 |
| 1954 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1955 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1956 |
| 1957 CreateDeterministicNetworkSession(); |
| 1958 |
| 1959 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1960 |
| 1961 scoped_refptr<SpdyStream> spdy_stream1; |
| 1962 TestCompletionCallback callback1; |
| 1963 GURL url1("http://www.google.com"); |
| 1964 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1965 BoundNetLog(), callback1.callback())); |
| 1966 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1967 |
| 1968 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1969 (*headers)["method"] = "GET"; |
| 1970 (*headers)["scheme"] = url1.scheme(); |
| 1971 (*headers)["host"] = url1.host(); |
| 1972 (*headers)["url"] = url1.path(); |
| 1973 (*headers)["version"] = "HTTP/1.1"; |
| 1974 |
| 1975 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1976 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1977 spdy_stream1->SendRequest(false); |
| 1978 |
| 1979 // Run until 1st read. |
| 1980 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1981 data.RunFor(1); |
| 1982 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1983 |
| 1984 // Drop the reference to the session. |
| 1985 session = NULL; |
| 1986 |
| 1987 // Run until GoAway. |
| 1988 data.RunFor(2); |
| 1989 |
| 1990 // Drop the reference to the stream which deletes its reference to the |
| 1991 // SpdySession. Only references to SpdySession are held by DoLoop and |
| 1992 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if |
| 1993 // SpdySession is deleted from the SpdySessionPool. |
| 1994 spdy_stream1 = NULL; |
| 1995 |
| 1996 data.RunFor(2); |
| 1997 EXPECT_TRUE(data.at_write_eof()); |
| 1998 EXPECT_TRUE(data.at_read_eof()); |
| 1999 } |
| 2000 |
1930 } // namespace net | 2001 } // namespace net |
OLD | NEW |