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 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 Loading... |
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 |
OLD | NEW |