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

Side by Side Diff: net/spdy/spdy_session_spdy3_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 | « net/spdy/spdy_session_spdy2_unittest.cc ('k') | no next file » | 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/location.h" 7 #include "base/location.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h" 9 #include "base/memory/scoped_vector.h"
10 #include "base/pending_task.h" 10 #include "base/pending_task.h"
(...skipping 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 data.RunFor(6); 1929 data.RunFor(6);
1930 1930
1931 // Verify task observer's executed_count is 1, which indicates DoRead has 1931 // Verify task observer's executed_count is 1, which indicates DoRead has
1932 // posted only one task and thus yielded though there is data available for it 1932 // posted only one task and thus yielded though there is data available for it
1933 // to read. 1933 // to read.
1934 EXPECT_EQ(1u, observer.executed_count()); 1934 EXPECT_EQ(1u, observer.executed_count());
1935 EXPECT_TRUE(data.at_write_eof()); 1935 EXPECT_TRUE(data.at_write_eof());
1936 EXPECT_TRUE(data.at_read_eof()); 1936 EXPECT_TRUE(data.at_read_eof());
1937 } 1937 }
1938 1938
1939 // Test that SpdySession::DoRead yields while reading the data. This test makes 1939 // Test that SpdySession::DoRead() tests interactions of yielding + async,
1940 // 4 reads of kMaxReadBytes / 4 (-spdy_data_frame_size), one read of 1940 // by doing the following MockReads.
1941 // kMaxReadBytes (-spdy_data_frame_size), and some reads of kMaxReadBytes + 8k 1941 //
1942 // (-spdy_data_frame_size), bytes of data available on the socket for reading. 1942 // MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
1943 // It then verifies that DoRead has yielded even though there is data available 1943 // ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
1944 // for it to read (i.e, socket()->Read didn't return ERR_IO_PENDING during 1944 //
1945 // socket reads). Also verifies that SpdySession reads only 1945 // The above reads 26K synchronously. Since that is less that 32K, we will
1946 // SpdySession::kReadBufferSize data from the underlying transport. 1946 // attempt to read again. However, that DoRead() will return ERR_IO_PENDING
1947 // TODO(rtennti): Make this test work after fixes to DeterministicSocketData. 1947 // (because of async read), so DoRead() will yield. When we come back, DoRead()
1948 TEST_F(SpdySessionSpdy3Test, DISABLED_TestYieldingDuringLargeReadData) { 1948 // will read the results from the async read, and rest of the data
1949 // synchronously.
1950 TEST_F(SpdySessionSpdy3Test, TestYieldingDuringAsyncReadData) {
1949 MockConnect connect_data(SYNCHRONOUS, OK); 1951 MockConnect connect_data(SYNCHRONOUS, OK);
1950 BufferedSpdyFramer framer(3, false); 1952 BufferedSpdyFramer framer(3, false);
1951 1953
1952 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); 1954 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
1953 MockWrite writes[] = { 1955 MockWrite writes[] = {
1954 CreateMockWrite(*req1, 0), 1956 CreateMockWrite(*req1, 0),
1955 }; 1957 };
1956 1958
1957 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). 1959 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
1958 ASSERT_EQ(32 * 1024, kMaxReadBytes); 1960 ASSERT_EQ(32 * 1024, kMaxReadBytes);
1959 TestDataStream test_stream; 1961 TestDataStream test_stream;
1960 const int kSmallPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); 1962 const int kEightKPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size();
1961 scoped_refptr<net::IOBuffer> small_payload( 1963 scoped_refptr<net::IOBuffer> eightk_payload(
1962 new net::IOBuffer(kSmallPayloadSize)); 1964 new net::IOBuffer(kEightKPayloadSize));
1963 char* small_payload_data = small_payload->data(); 1965 char* eightk_payload_data = eightk_payload->data();
1964 test_stream.GetBytes(small_payload_data, kSmallPayloadSize); 1966 test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
1965 1967
1966 // Build buffer of size kMaxReadBytes - (-spdy_data_frame_size). 1968 // Build buffer of 2k size.
1967 TestDataStream test_stream1; 1969 TestDataStream test_stream2;
1968 const int kMaxReadBytesPayloadSize = kMaxReadBytes - SpdyDataFrame::size(); 1970 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
1969 scoped_refptr<net::IOBuffer> max_bytes_payload( 1971 scoped_refptr<net::IOBuffer> twok_payload(
1970 new net::IOBuffer(kMaxReadBytesPayloadSize)); 1972 new net::IOBuffer(kTwoKPayloadSize));
1971 char* max_bytes_payload_data = max_bytes_payload->data(); 1973 char* twok_payload_data = twok_payload->data();
1972 test_stream1.GetBytes(max_bytes_payload_data, kMaxReadBytesPayloadSize); 1974 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
1973 1975
1974 // Build buffer of size kMaxReadBytes + kSmallPayloadSize 1976 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
1975 // (-spdy_data_frame_size). 1977 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
1976 TestDataStream test_stream2; 1978 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
1977 const int kLargePayloadSize = 1979 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
1978 kMaxReadBytes + kSmallPayloadSize - SpdyDataFrame::size();
1979 scoped_refptr<net::IOBuffer> large_payload(
1980 new net::IOBuffer(kLargePayloadSize));
1981 char* large_payload_data = large_payload->data();
1982 test_stream2.GetBytes(large_payload_data, kLargePayloadSize);
1983
1984 scoped_ptr<SpdyFrame> small_data_frame(framer.CreateDataFrame(
1985 1, small_payload_data, kSmallPayloadSize, DATA_FLAG_NONE));
1986 scoped_ptr<SpdyFrame> max_bytes_data_frame(framer.CreateDataFrame(
1987 1, max_bytes_payload_data, kMaxReadBytesPayloadSize, DATA_FLAG_NONE));
1988 scoped_ptr<SpdyFrame> large_data_frame(framer.CreateDataFrame(
1989 1, large_payload_data, kLargePayloadSize, DATA_FLAG_NONE));
1990 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( 1980 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
1991 1, "h", 1, DATA_FLAG_FIN)); 1981 1, "h", 1, DATA_FLAG_FIN));
1992 1982
1993 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); 1983 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
1994 1984
1995 MockRead reads[] = { 1985 MockRead reads[] = {
1996 CreateMockRead(*resp1, 1), 1986 CreateMockRead(*resp1, 1),
1997 CreateMockRead(*small_data_frame, 2), 1987 CreateMockRead(*eightk_data_frame, 2),
1998 CreateMockRead(*small_data_frame, 3, SYNCHRONOUS), 1988 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
1999 CreateMockRead(*small_data_frame, 4, SYNCHRONOUS), 1989 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
2000 CreateMockRead(*small_data_frame, 5, SYNCHRONOUS), 1990 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
2001 CreateMockRead(*max_bytes_data_frame, 6), 1991 CreateMockRead(*eightk_data_frame, 6, ASYNC),
2002 CreateMockRead(*large_data_frame, 7, SYNCHRONOUS), 1992 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
2003 CreateMockRead(*finish_data_frame, 8, SYNCHRONOUS), 1993 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
2004 MockRead(ASYNC, 0, 9) // EOF 1994 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
1995 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
1996 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
1997 MockRead(ASYNC, 0, 12) // EOF
2005 }; 1998 };
2006 1999
2007 // Create SpdySession and SpdyStream and send the request. 2000 // Create SpdySession and SpdyStream and send the request.
2008 DeterministicSocketData data(reads, arraysize(reads), 2001 DeterministicSocketData data(reads, arraysize(reads),
2009 writes, arraysize(writes)); 2002 writes, arraysize(writes));
2010 data.set_connect_data(connect_data); 2003 data.set_connect_data(connect_data);
2011 session_deps_.host_resolver->set_synchronous_mode(true); 2004 session_deps_.host_resolver->set_synchronous_mode(true);
2012 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); 2005 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2013 2006
2014 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); 2007 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
(...skipping 14 matching lines...) Expand all
2029 (*headers)[":method"] = "GET"; 2022 (*headers)[":method"] = "GET";
2030 (*headers)[":scheme"] = url1.scheme(); 2023 (*headers)[":scheme"] = url1.scheme();
2031 (*headers)[":host"] = url1.host(); 2024 (*headers)[":host"] = url1.host();
2032 (*headers)[":path"] = url1.path(); 2025 (*headers)[":path"] = url1.path();
2033 (*headers)[":version"] = "HTTP/1.1"; 2026 (*headers)[":version"] = "HTTP/1.1";
2034 2027
2035 spdy_stream1->set_spdy_headers(headers.Pass()); 2028 spdy_stream1->set_spdy_headers(headers.Pass());
2036 EXPECT_TRUE(spdy_stream1->HasUrl()); 2029 EXPECT_TRUE(spdy_stream1->HasUrl());
2037 spdy_stream1->SendRequest(false); 2030 spdy_stream1->SendRequest(false);
2038 2031
2039 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. 2032 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks.
2040 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); 2033 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
2041 2034
2042 // Run until 1st read. 2035 // Run until 1st read.
2043 EXPECT_EQ(0u, spdy_stream1->stream_id()); 2036 EXPECT_EQ(0u, spdy_stream1->stream_id());
2044 data.RunFor(2); 2037 data.RunFor(2);
2045 EXPECT_EQ(1u, spdy_stream1->stream_id()); 2038 EXPECT_EQ(1u, spdy_stream1->stream_id());
2046 EXPECT_EQ(0u, observer.executed_count()); 2039 EXPECT_EQ(0u, observer.executed_count());
2047 2040
2048 // Read all the data and verify SpdySession::DoRead has posted a task. 2041 // Read all the data and verify SpdySession::DoRead has posted a task.
2049 data.RunFor(10); 2042 data.RunFor(12);
2050 2043
2051 // Verify task observer's executed_count is 1, which indicates DoRead has 2044 // Verify task observer's executed_count is 1, which indicates DoRead has
2052 // posted only one task and thus yielded though there is data available for 2045 // posted only one task and thus yielded though there is data available for
2053 // it to read. 2046 // it to read.
2054 EXPECT_EQ(1u, observer.executed_count()); 2047 EXPECT_EQ(1u, observer.executed_count());
2055 EXPECT_TRUE(data.at_write_eof()); 2048 EXPECT_TRUE(data.at_write_eof());
2056 EXPECT_TRUE(data.at_read_eof()); 2049 EXPECT_TRUE(data.at_read_eof());
2057 } 2050 }
2058 2051
2052 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to
2053 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because
2054 // GoAway could delete the SpdySession from the SpdySessionPool and the last
2055 // reference to SpdySession.
2056 TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) {
2057 MockConnect connect_data(SYNCHRONOUS, OK);
2058 BufferedSpdyFramer framer(3, false);
2059
2060 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
2061 MockWrite writes[] = {
2062 CreateMockWrite(*req1, 0),
2063 };
2064
2065 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
2066 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true));
2067 scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway());
2068
2069 MockRead reads[] = {
2070 CreateMockRead(*resp1, 1),
2071 CreateMockRead(*body1, 2),
2072 CreateMockRead(*goaway, 3),
2073 MockRead(ASYNC, 0, 4) // EOF
2074 };
2075
2076 // Create SpdySession and SpdyStream and send the request.
2077 DeterministicSocketData data(reads, arraysize(reads),
2078 writes, arraysize(writes));
2079 data.set_connect_data(connect_data);
2080 session_deps_.host_resolver->set_synchronous_mode(true);
2081 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
2082
2083 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
2084 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
2085
2086 CreateDeterministicNetworkSession();
2087
2088 scoped_refptr<SpdySession> session = CreateInitializedSession();
2089
2090 scoped_refptr<SpdyStream> spdy_stream1;
2091 TestCompletionCallback callback1;
2092 GURL url1("http://www.google.com");
2093 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1,
2094 BoundNetLog(), callback1.callback()));
2095 EXPECT_EQ(0u, spdy_stream1->stream_id());
2096
2097 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
2098 (*headers)[":method"] = "GET";
2099 (*headers)[":scheme"] = url1.scheme();
2100 (*headers)[":host"] = url1.host();
2101 (*headers)[":path"] = url1.path();
2102 (*headers)[":version"] = "HTTP/1.1";
2103
2104 spdy_stream1->set_spdy_headers(headers.Pass());
2105 EXPECT_TRUE(spdy_stream1->HasUrl());
2106 spdy_stream1->SendRequest(false);
2107
2108 // Run until 1st read.
2109 EXPECT_EQ(0u, spdy_stream1->stream_id());
2110 data.RunFor(1);
2111 EXPECT_EQ(1u, spdy_stream1->stream_id());
2112
2113 // Drop the reference to the session.
2114 session = NULL;
2115
2116 // Run until GoAway.
2117 data.RunFor(2);
2118
2119 // Drop the reference to the stream which deletes its reference to the
2120 // SpdySession. Only references to SpdySession are held by DoLoop and
2121 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if
2122 // SpdySession is deleted from the SpdySessionPool.
2123 spdy_stream1 = NULL;
2124
2125 data.RunFor(2);
2126 EXPECT_TRUE(data.at_write_eof());
2127 EXPECT_TRUE(data.at_read_eof());
2128 }
2129
2059 } // namespace net 2130 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_session_spdy2_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698