| Index: net/spdy/spdy_session_spdy2_unittest.cc
|
| ===================================================================
|
| --- net/spdy/spdy_session_spdy2_unittest.cc (revision 192196)
|
| +++ net/spdy/spdy_session_spdy2_unittest.cc (working copy)
|
| @@ -4,18 +4,13 @@
|
|
|
| #include "net/spdy/spdy_session.h"
|
|
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/memory/scoped_vector.h"
|
| #include "net/base/host_cache.h"
|
| -#include "net/base/io_buffer.h"
|
| #include "net/base/ip_endpoint.h"
|
| #include "net/base/net_log_unittest.h"
|
| #include "net/base/request_priority.h"
|
| #include "net/base/test_data_directory.h"
|
| -#include "net/base/test_data_stream.h"
|
| #include "net/spdy/spdy_io_buffer.h"
|
| #include "net/spdy/spdy_session_pool.h"
|
| -#include "net/spdy/spdy_session_test_util.h"
|
| #include "net/spdy/spdy_stream.h"
|
| #include "net/spdy/spdy_stream_test_util.h"
|
| #include "net/spdy/spdy_test_util_common.h"
|
| @@ -1585,376 +1580,6 @@
|
| spdy_session_pool_->Remove(session);
|
| }
|
|
|
| -// Test that SpdySession::DoRead reads data from the socket without yielding.
|
| -// This test makes 32k - 1 bytes of data available on the socket for reading. It
|
| -// then verifies that it has read all the available data without yielding.
|
| -TEST_F(SpdySessionSpdy2Test, ReadDataWithoutYielding) {
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - BufferedSpdyFramer framer(2, false);
|
| -
|
| - scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(*req1, 0),
|
| - };
|
| -
|
| - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
|
| - ASSERT_EQ(32 * 1024, kMaxReadBytes);
|
| - const int kPayloadSize =
|
| - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
|
| - TestDataStream test_stream;
|
| - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
|
| - char* payload_data = payload->data();
|
| - test_stream.GetBytes(payload_data, kPayloadSize);
|
| -
|
| - scoped_ptr<SpdyFrame> partial_data_frame(
|
| - framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
|
| - scoped_ptr<SpdyFrame> finish_data_frame(
|
| - framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN));
|
| -
|
| - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
|
| -
|
| - // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k
|
| - // bytes.
|
| - MockRead reads[] = {
|
| - CreateMockRead(*resp1, 1),
|
| - CreateMockRead(*partial_data_frame, 2),
|
| - CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
|
| - CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
|
| - CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS),
|
| - MockRead(ASYNC, 0, 6) // EOF
|
| - };
|
| -
|
| - // Create SpdySession and SpdyStream and send the request.
|
| - DeterministicSocketData data(reads, arraysize(reads),
|
| - writes, arraysize(writes));
|
| - data.set_connect_data(connect_data);
|
| - session_deps_.host_resolver->set_synchronous_mode(true);
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
|
| - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
|
| -
|
| - CreateDeterministicNetworkSession();
|
| -
|
| - scoped_refptr<SpdySession> session = CreateInitializedSession();
|
| -
|
| - GURL url1("http://www.google.com");
|
| - scoped_refptr<SpdyStream> spdy_stream1 =
|
| - CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
|
| - ASSERT_TRUE(spdy_stream1.get() != NULL);
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
|
| - (*headers)["method"] = "GET";
|
| - (*headers)["scheme"] = url1.scheme();
|
| - (*headers)["host"] = url1.host();
|
| - (*headers)["url"] = url1.path();
|
| - (*headers)["version"] = "HTTP/1.1";
|
| -
|
| - spdy_stream1->set_spdy_headers(headers.Pass());
|
| - EXPECT_TRUE(spdy_stream1->HasUrl());
|
| - spdy_stream1->SendRequest(false);
|
| -
|
| - // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task.
|
| - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
|
| -
|
| - // Run until 1st read.
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| - data.RunFor(2);
|
| - EXPECT_EQ(1u, spdy_stream1->stream_id());
|
| - EXPECT_EQ(0u, observer.executed_count());
|
| -
|
| - // Read all the data and verify SpdySession::DoRead has not posted a task.
|
| - data.RunFor(4);
|
| -
|
| - // Verify task observer's executed_count is zero, which indicates DoRead read
|
| - // all the available data.
|
| - EXPECT_EQ(0u, observer.executed_count());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| - EXPECT_TRUE(data.at_read_eof());
|
| -}
|
| -
|
| -// Test that SpdySession::DoRead yields while reading the data. This test makes
|
| -// 32k + 1 bytes of data available on the socket for reading. It then verifies
|
| -// that DoRead has yielded even though there is data available for it to read
|
| -// (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads).
|
| -TEST_F(SpdySessionSpdy2Test, TestYieldingDuringReadData) {
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - BufferedSpdyFramer framer(2, false);
|
| -
|
| - scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(*req1, 0),
|
| - };
|
| -
|
| - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
|
| - ASSERT_EQ(32 * 1024, kMaxReadBytes);
|
| - const int kPayloadSize =
|
| - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
|
| - TestDataStream test_stream;
|
| - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize));
|
| - char* payload_data = payload->data();
|
| - test_stream.GetBytes(payload_data, kPayloadSize);
|
| -
|
| - scoped_ptr<SpdyFrame> partial_data_frame(
|
| - framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE));
|
| - scoped_ptr<SpdyFrame> finish_data_frame(
|
| - framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN));
|
| -
|
| - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
|
| -
|
| - // Write 1 byte more than kMaxReadBytes to check that DoRead yields.
|
| - MockRead reads[] = {
|
| - CreateMockRead(*resp1, 1),
|
| - CreateMockRead(*partial_data_frame, 2),
|
| - CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS),
|
| - CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS),
|
| - CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS),
|
| - CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS),
|
| - MockRead(ASYNC, 0, 7) // EOF
|
| - };
|
| -
|
| - // Create SpdySession and SpdyStream and send the request.
|
| - DeterministicSocketData data(reads, arraysize(reads),
|
| - writes, arraysize(writes));
|
| - data.set_connect_data(connect_data);
|
| - session_deps_.host_resolver->set_synchronous_mode(true);
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
|
| - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
|
| -
|
| - CreateDeterministicNetworkSession();
|
| -
|
| - scoped_refptr<SpdySession> session = CreateInitializedSession();
|
| -
|
| - GURL url1("http://www.google.com");
|
| - scoped_refptr<SpdyStream> spdy_stream1 =
|
| - CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
|
| - ASSERT_TRUE(spdy_stream1.get() != NULL);
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
|
| - (*headers)["method"] = "GET";
|
| - (*headers)["scheme"] = url1.scheme();
|
| - (*headers)["host"] = url1.host();
|
| - (*headers)["url"] = url1.path();
|
| - (*headers)["version"] = "HTTP/1.1";
|
| -
|
| - spdy_stream1->set_spdy_headers(headers.Pass());
|
| - EXPECT_TRUE(spdy_stream1->HasUrl());
|
| - spdy_stream1->SendRequest(false);
|
| -
|
| - // Set up the TaskObserver to verify SpdySession::DoRead posts a task.
|
| - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
|
| -
|
| - // Run until 1st read.
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| - data.RunFor(2);
|
| - EXPECT_EQ(1u, spdy_stream1->stream_id());
|
| - EXPECT_EQ(0u, observer.executed_count());
|
| -
|
| - // Read all the data and verify SpdySession::DoRead has posted a task.
|
| - data.RunFor(6);
|
| -
|
| - // Verify task observer's executed_count is 1, which indicates DoRead has
|
| - // posted only one task and thus yielded though there is data available for it
|
| - // to read.
|
| - EXPECT_EQ(1u, observer.executed_count());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| - EXPECT_TRUE(data.at_read_eof());
|
| -}
|
| -
|
| -// Test that SpdySession::DoRead() tests interactions of yielding + async,
|
| -// by doing the following MockReads.
|
| -//
|
| -// MockRead of SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K
|
| -// ASYNC 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 8K, SYNCHRONOUS 2K.
|
| -//
|
| -// The above reads 26K synchronously. Since that is less that 32K, we will
|
| -// attempt to read again. However, that DoRead() will return ERR_IO_PENDING
|
| -// (because of async read), so DoRead() will yield. When we come back, DoRead()
|
| -// will read the results from the async read, and rest of the data
|
| -// synchronously.
|
| -TEST_F(SpdySessionSpdy2Test, TestYieldingDuringAsyncReadData) {
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - BufferedSpdyFramer framer(2, false);
|
| -
|
| - scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(*req1, 0),
|
| - };
|
| -
|
| - // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size).
|
| - ASSERT_EQ(32 * 1024, kMaxReadBytes);
|
| - TestDataStream test_stream;
|
| - const int kEightKPayloadSize =
|
| - kMaxReadBytes / 4 - framer.GetControlFrameHeaderSize();
|
| - scoped_refptr<net::IOBuffer> eightk_payload(
|
| - new net::IOBuffer(kEightKPayloadSize));
|
| - char* eightk_payload_data = eightk_payload->data();
|
| - test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize);
|
| -
|
| - // Build buffer of 2k size.
|
| - TestDataStream test_stream2;
|
| - const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024;
|
| - scoped_refptr<net::IOBuffer> twok_payload(
|
| - new net::IOBuffer(kTwoKPayloadSize));
|
| - char* twok_payload_data = twok_payload->data();
|
| - test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize);
|
| -
|
| - scoped_ptr<SpdyFrame> eightk_data_frame(framer.CreateDataFrame(
|
| - 1, eightk_payload_data, kEightKPayloadSize, DATA_FLAG_NONE));
|
| - scoped_ptr<SpdyFrame> twok_data_frame(framer.CreateDataFrame(
|
| - 1, twok_payload_data, kTwoKPayloadSize, DATA_FLAG_NONE));
|
| - scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame(
|
| - 1, "h", 1, DATA_FLAG_FIN));
|
| -
|
| - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
|
| -
|
| - MockRead reads[] = {
|
| - CreateMockRead(*resp1, 1),
|
| - CreateMockRead(*eightk_data_frame, 2),
|
| - CreateMockRead(*eightk_data_frame, 3, SYNCHRONOUS),
|
| - CreateMockRead(*eightk_data_frame, 4, SYNCHRONOUS),
|
| - CreateMockRead(*twok_data_frame, 5, SYNCHRONOUS),
|
| - CreateMockRead(*eightk_data_frame, 6, ASYNC),
|
| - CreateMockRead(*eightk_data_frame, 7, SYNCHRONOUS),
|
| - CreateMockRead(*eightk_data_frame, 8, SYNCHRONOUS),
|
| - CreateMockRead(*eightk_data_frame, 9, SYNCHRONOUS),
|
| - CreateMockRead(*twok_data_frame, 10, SYNCHRONOUS),
|
| - CreateMockRead(*finish_data_frame, 11, SYNCHRONOUS),
|
| - MockRead(ASYNC, 0, 12) // EOF
|
| - };
|
| -
|
| - // Create SpdySession and SpdyStream and send the request.
|
| - DeterministicSocketData data(reads, arraysize(reads),
|
| - writes, arraysize(writes));
|
| - data.set_connect_data(connect_data);
|
| - session_deps_.host_resolver->set_synchronous_mode(true);
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
|
| - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
|
| -
|
| - CreateDeterministicNetworkSession();
|
| -
|
| - scoped_refptr<SpdySession> session = CreateInitializedSession();
|
| -
|
| - GURL url1("http://www.google.com");
|
| - scoped_refptr<SpdyStream> spdy_stream1 =
|
| - CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
|
| - ASSERT_TRUE(spdy_stream1.get() != NULL);
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
|
| - (*headers)["method"] = "GET";
|
| - (*headers)["scheme"] = url1.scheme();
|
| - (*headers)["host"] = url1.host();
|
| - (*headers)["url"] = url1.path();
|
| - (*headers)["version"] = "HTTP/1.1";
|
| -
|
| - spdy_stream1->set_spdy_headers(headers.Pass());
|
| - EXPECT_TRUE(spdy_stream1->HasUrl());
|
| - spdy_stream1->SendRequest(false);
|
| -
|
| - // Set up the TaskObserver to monitor SpdySession::DoRead posting of tasks.
|
| - SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead");
|
| -
|
| - // Run until 1st read.
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| - data.RunFor(2);
|
| - EXPECT_EQ(1u, spdy_stream1->stream_id());
|
| - EXPECT_EQ(0u, observer.executed_count());
|
| -
|
| - // Read all the data and verify SpdySession::DoRead has posted a task.
|
| - data.RunFor(12);
|
| -
|
| - // Verify task observer's executed_count is 1, which indicates DoRead has
|
| - // posted only one task and thus yielded though there is data available for
|
| - // it to read.
|
| - EXPECT_EQ(1u, observer.executed_count());
|
| - EXPECT_TRUE(data.at_write_eof());
|
| - EXPECT_TRUE(data.at_read_eof());
|
| -}
|
| -
|
| -// Send a GoAway frame when SpdySession is in DoLoop. If scoped_refptr to
|
| -// <SpdySession> is deleted from SpdySession::DoLoop(), we get a crash because
|
| -// GoAway could delete the SpdySession from the SpdySessionPool and the last
|
| -// reference to SpdySession.
|
| -TEST_F(SpdySessionSpdy2Test, GoAwayWhileInDoLoop) {
|
| - MockConnect connect_data(SYNCHRONOUS, OK);
|
| - BufferedSpdyFramer framer(2, false);
|
| -
|
| - scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM));
|
| - MockWrite writes[] = {
|
| - CreateMockWrite(*req1, 0),
|
| - };
|
| -
|
| - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
|
| - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, true));
|
| - scoped_ptr<SpdyFrame> goaway(ConstructSpdyGoAway());
|
| -
|
| - MockRead reads[] = {
|
| - CreateMockRead(*resp1, 1),
|
| - CreateMockRead(*body1, 2),
|
| - CreateMockRead(*goaway, 3),
|
| - MockRead(ASYNC, 0, 4) // EOF
|
| - };
|
| -
|
| - // Create SpdySession and SpdyStream and send the request.
|
| - DeterministicSocketData data(reads, arraysize(reads),
|
| - writes, arraysize(writes));
|
| - data.set_connect_data(connect_data);
|
| - session_deps_.host_resolver->set_synchronous_mode(true);
|
| - session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
|
| -
|
| - SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
|
| - session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl);
|
| -
|
| - CreateDeterministicNetworkSession();
|
| -
|
| - scoped_refptr<SpdySession> session = CreateInitializedSession();
|
| -
|
| - GURL url1("http://www.google.com");
|
| - scoped_refptr<SpdyStream> spdy_stream1 =
|
| - CreateStreamSynchronously(session, url1, MEDIUM, BoundNetLog());
|
| - ASSERT_TRUE(spdy_stream1.get() != NULL);
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| -
|
| - scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock);
|
| - (*headers)["method"] = "GET";
|
| - (*headers)["scheme"] = url1.scheme();
|
| - (*headers)["host"] = url1.host();
|
| - (*headers)["url"] = url1.path();
|
| - (*headers)["version"] = "HTTP/1.1";
|
| -
|
| - spdy_stream1->set_spdy_headers(headers.Pass());
|
| - EXPECT_TRUE(spdy_stream1->HasUrl());
|
| - spdy_stream1->SendRequest(false);
|
| -
|
| - // Run until 1st read.
|
| - EXPECT_EQ(0u, spdy_stream1->stream_id());
|
| - data.RunFor(1);
|
| - EXPECT_EQ(1u, spdy_stream1->stream_id());
|
| -
|
| - // Drop the reference to the session.
|
| - session = NULL;
|
| -
|
| - // Run until GoAway.
|
| - data.RunFor(2);
|
| -
|
| - // Drop the reference to the stream which deletes its reference to the
|
| - // SpdySession. Only references to SpdySession are held by DoLoop and
|
| - // SpdySessionPool. If DoLoop doesn't hold the reference, we get a crash if
|
| - // SpdySession is deleted from the SpdySessionPool.
|
| - spdy_stream1 = NULL;
|
| -
|
| - data.RunFor(2);
|
| - EXPECT_TRUE(data.at_write_eof());
|
| - EXPECT_TRUE(data.at_read_eof());
|
| -}
|
| -
|
| // Within this framework, a SpdySession should be initialized with
|
| // flow control disabled and with protocol version 2.
|
| TEST_F(SpdySessionSpdy2Test, ProtocolNegotiation) {
|
|
|