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/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 Loading... |
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 6K, 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 6k size. |
1967 TestDataStream test_stream1; | 1969 TestDataStream test_stream1; |
1968 const int kMaxReadBytesPayloadSize = kMaxReadBytes - SpdyDataFrame::size(); | 1970 const int kSixKPayloadSize = kEightKPayloadSize - 2 * 1024; |
1969 scoped_refptr<net::IOBuffer> max_bytes_payload( | 1971 scoped_refptr<net::IOBuffer> sixk_bytes_payload( |
1970 new net::IOBuffer(kMaxReadBytesPayloadSize)); | 1972 new net::IOBuffer(kSixKPayloadSize)); |
1971 char* max_bytes_payload_data = max_bytes_payload->data(); | 1973 char* sixk_bytes_payload_data = sixk_bytes_payload->data(); |
1972 test_stream1.GetBytes(max_bytes_payload_data, kMaxReadBytesPayloadSize); | 1974 test_stream1.GetBytes(sixk_bytes_payload_data, kSixKPayloadSize); |
1973 | 1975 |
1974 // Build buffer of size kMaxReadBytes + kSmallPayloadSize | 1976 // Build buffer of 2k size. |
1975 // (-spdy_data_frame_size). | |
1976 TestDataStream test_stream2; | 1977 TestDataStream test_stream2; |
1977 const int kLargePayloadSize = | 1978 const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; |
1978 kMaxReadBytes + kSmallPayloadSize - SpdyDataFrame::size(); | 1979 scoped_refptr<net::IOBuffer> twok_payload( |
1979 scoped_refptr<net::IOBuffer> large_payload( | 1980 new net::IOBuffer(kTwoKPayloadSize)); |
1980 new net::IOBuffer(kLargePayloadSize)); | 1981 char* twok_payload_data = twok_payload->data(); |
1981 char* large_payload_data = large_payload->data(); | 1982 test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); |
1982 test_stream2.GetBytes(large_payload_data, kLargePayloadSize); | |
1983 | 1983 |
1984 scoped_ptr<SpdyFrame> small_data_frame(framer.CreateDataFrame( | 1984 scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame( |
1985 1, small_payload_data, kSmallPayloadSize, DATA_FLAG_NONE)); | 1985 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE)); |
1986 scoped_ptr<SpdyFrame> max_bytes_data_frame(framer.CreateDataFrame( | 1986 scoped_ptr<SpdyFrame> sixk_bytes_data_frame(framer.CreateDataFrame( |
1987 1, max_bytes_payload_data, kMaxReadBytesPayloadSize, DATA_FLAG_NONE)); | 1987 1, sixk_bytes_payload_data, kSixKPayloadSize, DATA_FLAG_NONE)); |
1988 scoped_ptr<SpdyFrame> large_data_frame(framer.CreateDataFrame( | 1988 scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame( |
1989 1, large_payload_data, kLargePayloadSize, DATA_FLAG_NONE)); | 1989 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE)); |
1990 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( | 1990 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( |
1991 1, "h", 1, DATA_FLAG_FIN)); | 1991 1, "h", 1, DATA_FLAG_FIN)); |
1992 | 1992 |
1993 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); | 1993 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
1994 | 1994 |
1995 MockRead reads[] = { | 1995 MockRead reads[] = { |
1996 CreateMockRead(*resp1, 1), | 1996 CreateMockRead(*resp1, 1), |
1997 CreateMockRead(*small_data_frame, 2), | 1997 CreateMockRead(*eightk_data_frame, 2), |
1998 CreateMockRead(*small_data_frame, 3, SYNCHRONOUS), | 1998 CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS), |
1999 CreateMockRead(*small_data_frame, 4, SYNCHRONOUS), | 1999 CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS), |
2000 CreateMockRead(*small_data_frame, 5, SYNCHRONOUS), | 2000 CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS), |
2001 CreateMockRead(*max_bytes_data_frame, 6), | 2001 CreateMockRead(*sixk_bytes_data_frame, 6, ASYNC), |
2002 CreateMockRead(*large_data_frame, 7, SYNCHRONOUS), | 2002 CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS), |
2003 CreateMockRead(*finish_data_frame, 8, SYNCHRONOUS), | 2003 CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS), |
2004 MockRead(ASYNC, 0, 9) // EOF | 2004 CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS), |
| 2005 CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS), |
| 2006 CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS), |
| 2007 MockRead(ASYNC, 0, 12) // EOF |
2005 }; | 2008 }; |
2006 | 2009 |
2007 // Create SpdySession and SpdyStream and send the request. | 2010 // Create SpdySession and SpdyStream and send the request. |
2008 DeterministicSocketData data(reads, arraysize(reads), | 2011 DeterministicSocketData data(reads, arraysize(reads), |
2009 writes, arraysize(writes)); | 2012 writes, arraysize(writes)); |
2010 data.set_connect_data(connect_data); | 2013 data.set_connect_data(connect_data); |
2011 session_deps_.host_resolver->set_synchronous_mode(true); | 2014 session_deps_.host_resolver->set_synchronous_mode(true); |
2012 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); | 2015 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
2013 | 2016 |
2014 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | 2017 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
(...skipping 14 matching lines...) Expand all Loading... |
2029 (*headers)[":method"] = "GET"; | 2032 (*headers)[":method"] = "GET"; |
2030 (*headers)[":scheme"] = url1.scheme(); | 2033 (*headers)[":scheme"] = url1.scheme(); |
2031 (*headers)[":host"] = url1.host(); | 2034 (*headers)[":host"] = url1.host(); |
2032 (*headers)[":path"] = url1.path(); | 2035 (*headers)[":path"] = url1.path(); |
2033 (*headers)[":version"] = "HTTP/1.1"; | 2036 (*headers)[":version"] = "HTTP/1.1"; |
2034 | 2037 |
2035 spdy_stream1->set_spdy_headers(headers.Pass()); | 2038 spdy_stream1->set_spdy_headers(headers.Pass()); |
2036 EXPECT_TRUE(spdy_stream1->HasUrl()); | 2039 EXPECT_TRUE(spdy_stream1->HasUrl()); |
2037 spdy_stream1->SendRequest(false); | 2040 spdy_stream1->SendRequest(false); |
2038 | 2041 |
2039 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. | 2042 // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks. |
2040 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); | 2043 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
2041 | 2044 |
2042 // Run until 1st read. | 2045 // Run until 1st read. |
2043 EXPECT_EQ(0u, spdy_stream1->stream_id()); | 2046 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
2044 data.RunFor(2); | 2047 data.RunFor(2); |
2045 EXPECT_EQ(1u, spdy_stream1->stream_id()); | 2048 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
2046 EXPECT_EQ(0u, observer.executed_count()); | 2049 EXPECT_EQ(0u, observer.executed_count()); |
2047 | 2050 |
2048 // Read all the data and verify SpdySession::DoRead has posted a task. | 2051 // Read all the data and verify SpdySession::DoRead has posted a task. |
2049 data.RunFor(10); | 2052 data.RunFor(12); |
2050 | 2053 |
2051 // Verify task observer's executed_count is 1, which indicates DoRead has | 2054 // 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 | 2055 // posted only one task and thus yielded though there is data available for |
2053 // it to read. | 2056 // it to read. |
2054 EXPECT_EQ(1u, observer.executed_count()); | 2057 EXPECT_EQ(1u, observer.executed_count()); |
2055 EXPECT_TRUE(data.at_write_eof()); | 2058 EXPECT_TRUE(data.at_write_eof()); |
2056 EXPECT_TRUE(data.at_read_eof()); | 2059 EXPECT_TRUE(data.at_read_eof()); |
2057 } | 2060 } |
2058 | 2061 |
| 2062 // Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to |
| 2063 // <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because |
| 2064 // GoAway could delete the SpdySession from the SpdySessionPool and the last |
| 2065 // reference to SpdySession. |
| 2066 TEST_F(SpdySessionSpdy3Test, GoAwayWhileInDoLoop) { |
| 2067 MockConnect connect_data(SYNCHRONOUS, OK); |
| 2068 BufferedSpdyFramer framer(3, false); |
| 2069 |
| 2070 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 2071 MockWrite writes[] = { |
| 2072 CreateMockWrite(*req1, 0), |
| 2073 }; |
| 2074 |
| 2075 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 2076 scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true)); |
| 2077 scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway()); |
| 2078 |
| 2079 MockRead reads[] = { |
| 2080 CreateMockRead(*resp1, 1), |
| 2081 CreateMockRead(*body1, 2), |
| 2082 CreateMockRead(*goaway, 3), |
| 2083 MockRead(ASYNC, 0, 4) // EOF |
| 2084 }; |
| 2085 |
| 2086 // Create SpdySession and SpdyStream and send the request. |
| 2087 DeterministicSocketData data(reads, arraysize(reads), |
| 2088 writes, arraysize(writes)); |
| 2089 data.set_connect_data(connect_data); |
| 2090 session_deps_.host_resolver->set_synchronous_mode(true); |
| 2091 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 2092 |
| 2093 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 2094 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 2095 |
| 2096 CreateDeterministicNetworkSession(); |
| 2097 |
| 2098 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 2099 |
| 2100 scoped_refptr<SpdyStream> spdy_stream1; |
| 2101 TestCompletionCallback callback1; |
| 2102 GURL url1("http://www.google.com"); |
| 2103 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 2104 BoundNetLog(), callback1.callback())); |
| 2105 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 2106 |
| 2107 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 2108 (*headers)[":method"] = "GET"; |
| 2109 (*headers)[":scheme"] = url1.scheme(); |
| 2110 (*headers)[":host"] = url1.host(); |
| 2111 (*headers)[":path"] = url1.path(); |
| 2112 (*headers)[":version"] = "HTTP/1.1"; |
| 2113 |
| 2114 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 2115 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 2116 spdy_stream1->SendRequest(false); |
| 2117 |
| 2118 // Run until 1st read. |
| 2119 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 2120 data.RunFor(1); |
| 2121 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 2122 |
| 2123 // Drop the reference to the session. |
| 2124 session = NULL; |
| 2125 |
| 2126 // Run until GoAway. |
| 2127 data.RunFor(2); |
| 2128 |
| 2129 // Drop the reference to the stream which deletes its reference to the |
| 2130 // SpdySession. Only references to SpdySession are held by DoLoop and |
| 2131 // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if |
| 2132 // SpdySession is deleted from the SpdySessionPool. |
| 2133 spdy_stream1 = NULL; |
| 2134 |
| 2135 data.RunFor(2); |
| 2136 EXPECT_TRUE(data.at_write_eof()); |
| 2137 EXPECT_TRUE(data.at_read_eof()); |
| 2138 } |
| 2139 |
2059 } // namespace net | 2140 } // namespace net |
OLD | NEW |