Index: net/spdy/spdy_network_transaction_spdy2_unittest.cc |
=================================================================== |
--- net/spdy/spdy_network_transaction_spdy2_unittest.cc (revision 176979) |
+++ net/spdy/spdy_network_transaction_spdy2_unittest.cc (working copy) |
@@ -13,7 +13,9 @@ |
#include "base/files/scoped_temp_dir.h" |
#include "base/memory/scoped_vector.h" |
#include "net/base/auth.h" |
+#include "net/base/io_buffer.h" |
#include "net/base/net_log_unittest.h" |
+#include "net/base/test_data_stream.h" |
#include "net/base/upload_bytes_element_reader.h" |
#include "net/base/upload_data_stream.h" |
#include "net/base/upload_file_element_reader.h" |
@@ -3929,6 +3931,187 @@ |
EXPECT_EQ("messagemessagemessagemessage", out.response_data); |
} |
+// Verify the case where SpdySession reads all the data synchronously without |
+// yielding. |
+TEST_P(SpdyNetworkTransactionSpdy2Test, BufferedSyncRead) { |
+ BufferedSpdyFramer framer(2, false); |
+ |
+ scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
+ MockWrite writes[] = { CreateMockWrite(*req) }; |
+ |
+ scoped_ptr<SpdyFrame> syn_reply( |
+ ConstructSpdyGetSynReply(NULL, 0, 1)); |
+ syn_reply->set_flags(CONTROL_FLAG_NONE); // Turn off FIN bit. |
+ |
+ const int kPayloadSize = 1600; |
+ net::TestDataStream test_stream; |
+ scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
+ test_stream.GetBytes(payload->data(), kPayloadSize); |
+ char* payload_data = payload->data(); |
+ std::string payload_content(payload_data, kPayloadSize); |
+ scoped_ptr<SpdyFrame> data_frame( |
+ framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_FIN)); |
+ const SpdyFrame* frames[2] = { |
+ syn_reply.get(), |
+ data_frame.get() |
+ }; |
+ char combined_frames[5000]; |
+ int combined_frames_len = |
+ CombineFrames(frames, arraysize(frames), |
+ combined_frames, arraysize(combined_frames)); |
+ |
+ MockRead reads[] = { |
+ MockRead(ASYNC, combined_frames, combined_frames_len), |
+ MockRead(ASYNC, 0, 0) // EOF |
+ }; |
+ |
+ DelayedSocketData data(1, reads, arraysize(reads), |
+ writes, arraysize(writes)); |
+ |
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), |
+ BoundNetLog(), GetParam(), NULL); |
+ helper.RunPreTestSetup(); |
+ helper.AddData(&data); |
+ HttpNetworkTransaction* trans = helper.trans(); |
+ |
+ TestCompletionCallback callback; |
+ int rv = trans->Start( |
+ &CreateGetRequest(), callback.callback(), BoundNetLog()); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ TransactionHelperResult out = helper.output(); |
+ out.rv = callback.WaitForResult(); |
+ EXPECT_EQ(out.rv, OK); |
+ |
+ const HttpResponseInfo* response = trans->GetResponseInfo(); |
+ EXPECT_TRUE(response->headers != NULL); |
+ EXPECT_TRUE(response->was_fetched_via_spdy); |
+ out.status_line = response->headers->GetStatusLine(); |
+ out.response_info = *response; // Make a copy so we can verify. |
+ |
+ // Read Data. |
+ TestCompletionCallback read_callback; |
+ |
+ std::string content; |
+ int reads_completed = 0; |
+ do { |
+ // Read data in chunks. |
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kPayloadSize)); |
+ rv = trans->Read(buf, kPayloadSize, read_callback.callback()); |
+ if (rv > 0) { |
+ content.append(buf->data(), rv); |
+ } else if (rv < 0) { |
+ FAIL() << "Unexpected read error: " << rv; |
+ } |
+ reads_completed++; |
+ } while (rv > 0); |
+ |
+ out.response_data.swap(content); |
+ |
+ // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |
+ // MockClientSocketFactory) are still alive. |
+ MessageLoop::current()->RunUntilIdle(); |
+ |
+ // Verify that we consumed all test data. |
+ helper.VerifyDataConsumed(); |
+ |
+ EXPECT_EQ(OK, out.rv); |
+ EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
+ EXPECT_EQ(payload_content, out.response_data); |
+} |
+ |
+// Verify the case where SpdySession reads kMaxReadBytes data synchronously and |
+// then reads more data after yielding. |
+TEST_P(SpdyNetworkTransactionSpdy2Test, BufferedASyncRead) { |
+ BufferedSpdyFramer framer(2, false); |
+ |
+ scoped_ptr<SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
+ MockWrite writes[] = { CreateMockWrite(*req) }; |
+ |
+ scoped_ptr<SpdyFrame> syn_reply( |
+ ConstructSpdyGetSynReply(NULL, 0, 1)); |
+ syn_reply->set_flags(CONTROL_FLAG_NONE); // Turn off FIN bit. |
+ |
+ const int kPayloadSize = kMaxReadBytes * 2; |
+ net::TestDataStream test_stream; |
+ scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
+ test_stream.GetBytes(payload->data(), kPayloadSize); |
+ char* payload_data = payload->data(); |
+ std::string payload_content(payload_data, kPayloadSize); |
+ scoped_ptr<SpdyFrame> data_frame( |
+ framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_FIN)); |
+ const SpdyFrame* frames[2] = { |
+ syn_reply.get(), |
+ data_frame.get() |
+ }; |
+ int heap_size = kPayloadSize * 2; |
+ scoped_ptr_malloc<char> combined_frames( |
+ reinterpret_cast<char*>(malloc(heap_size))); |
+ CHECK(combined_frames.get()); |
+ int combined_frames_len = |
+ CombineFrames(frames, arraysize(frames), |
+ combined_frames.get(), heap_size); |
+ |
+ MockRead reads[] = { |
+ MockRead(ASYNC, combined_frames.get(), combined_frames_len), |
+ MockRead(ASYNC, 0, 0) // EOF |
+ }; |
+ |
+ DelayedSocketData data(1, reads, arraysize(reads), |
+ writes, arraysize(writes)); |
+ |
+ NormalSpdyTransactionHelper helper(CreateGetRequest(), |
+ BoundNetLog(), GetParam(), NULL); |
+ helper.RunPreTestSetup(); |
+ helper.AddData(&data); |
+ HttpNetworkTransaction* trans = helper.trans(); |
+ |
+ TestCompletionCallback callback; |
+ int rv = trans->Start( |
+ &CreateGetRequest(), callback.callback(), BoundNetLog()); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ TransactionHelperResult out = helper.output(); |
+ out.rv = callback.WaitForResult(); |
+ EXPECT_EQ(out.rv, OK); |
+ |
+ const HttpResponseInfo* response = trans->GetResponseInfo(); |
+ EXPECT_TRUE(response->headers != NULL); |
+ EXPECT_TRUE(response->was_fetched_via_spdy); |
+ out.status_line = response->headers->GetStatusLine(); |
+ out.response_info = *response; // Make a copy so we can verify. |
+ |
+ // Read Data. |
+ TestCompletionCallback read_callback; |
+ |
+ std::string content; |
+ int reads_completed = 0; |
+ do { |
+ // Read data in chunks. |
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(kMaxReadBytes)); |
+ rv = trans->Read(buf, kMaxReadBytes, read_callback.callback()); |
+ if (rv > 0) { |
+ content.append(buf->data(), rv); |
+ } else if (rv < 0) { |
+ FAIL() << "Unexpected read error: " << rv; |
+ } |
+ reads_completed++; |
+ } while (rv > 0); |
+ |
+ out.response_data.swap(content); |
+ |
+ // Flush the MessageLoop while the SpdySessionDependencies (in particular, the |
+ // MockClientSocketFactory) are still alive. |
+ MessageLoop::current()->RunUntilIdle(); |
+ |
+ // Verify that we consumed all test data. |
+ helper.VerifyDataConsumed(); |
+ |
+ EXPECT_EQ(OK, out.rv); |
+ EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
+ EXPECT_EQ(payload_content, out.response_data); |
+} |
+ |
// Verify the case where we buffer data and close the connection. |
TEST_P(SpdyNetworkTransactionSpdy2Test, BufferedClosed) { |
BufferedSpdyFramer framer(2, false); |