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

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

Issue 12207122: SPDY - Added unit tests for use after free of SpdySession (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 10 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
« no previous file with comments | « no previous file | net/spdy/spdy_session_spdy3_unittest.cc » ('j') | 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 "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
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
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
OLDNEW
« no previous file with comments | « no previous file | net/spdy/spdy_session_spdy3_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698