Index: net/spdy/spdy_network_transaction_unittest.cc |
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc |
index d4f023f3de18e901792f553959ee999864057e36..877d90b2887330e0c3358a2de13ab4934c146d0e 100644 |
--- a/net/spdy/spdy_network_transaction_unittest.cc |
+++ b/net/spdy/spdy_network_transaction_unittest.cc |
@@ -4411,13 +4411,6 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { |
scoped_ptr<SpdyFrame> initial_settings_frame( |
spdy_util_.ConstructSpdySettings(initial_settings)); |
- // Construct the initial window update. |
- scoped_ptr<SpdyFrame> initial_window_update( |
- spdy_util_.ConstructSpdyWindowUpdate( |
- kSessionFlowControlStreamId, |
- kDefaultInitialRecvWindowSize - |
- SpdySession::GetInitialWindowSize(GetParam().protocol))); |
- |
// Construct the persisted SETTINGS frame. |
const SettingsMap& settings = |
spdy_session_pool->http_server_properties()->GetSpdySettings( |
@@ -4438,9 +4431,6 @@ TEST_P(SpdyNetworkTransactionTest, SettingsPlayback) { |
kHttp2ConnectionHeaderPrefixSize)); |
} |
writes.push_back(CreateMockWrite(*initial_settings_frame)); |
- if (GetParam().protocol >= kProtoSPDY31) { |
- writes.push_back(CreateMockWrite(*initial_window_update)); |
- } |
writes.push_back(CreateMockWrite(*settings_frame)); |
writes.push_back(CreateMockWrite(*req)); |
@@ -6148,23 +6138,64 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) { |
// Test that received data frames and sent WINDOW_UPDATE frames change |
// the recv_window_size_ correctly. |
TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { |
- const int32 initial_window_size = |
+ const int32 default_initial_window_size = |
SpdySession::GetInitialWindowSize(GetParam().protocol); |
- // Amount of body required to trigger a sent window update. |
- const size_t kTargetSize = initial_window_size / 2 + 1; |
+ // Session level maximum window size that is more than twice the default |
+ // initial window size so that an initial window update is sent. |
+ const int32 session_max_recv_window_size = 5 * 64 * 1024; |
+ ASSERT_LT(2 * default_initial_window_size, session_max_recv_window_size); |
+ // Stream level maximum window size that is less than the session level |
+ // maximum window size so that we test for confusion between the two. |
+ const int32 stream_max_recv_window_size = 4 * 64 * 1024; |
+ ASSERT_GT(session_max_recv_window_size, stream_max_recv_window_size); |
+ // Size of body to be sent. Has to be less than or equal to both window sizes |
+ // so that we do not run out of receiving window. Also has to be greater than |
+ // half of them so that it triggers both a session level and a stream level |
+ // window update frame. |
+ const int32 kTargetSize = 3 * 64 * 1024; |
+ ASSERT_GE(session_max_recv_window_size, kTargetSize); |
+ ASSERT_GE(stream_max_recv_window_size, kTargetSize); |
+ ASSERT_LT(session_max_recv_window_size / 2, kTargetSize); |
+ ASSERT_LT(stream_max_recv_window_size / 2, kTargetSize); |
+ // Size of each DATA frame. |
+ const int32 kChunkSize = 4096; |
+ // Size of window updates. |
+ ASSERT_EQ(0, session_max_recv_window_size / 2 % kChunkSize); |
+ const int32 session_window_update_delta = |
+ session_max_recv_window_size / 2 + kChunkSize; |
+ ASSERT_EQ(0, stream_max_recv_window_size / 2 % kChunkSize); |
+ const int32 stream_window_update_delta = |
+ stream_max_recv_window_size / 2 + kChunkSize; |
+ SettingsMap initial_settings; |
+ initial_settings[SETTINGS_MAX_CONCURRENT_STREAMS] = |
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); |
+ initial_settings[SETTINGS_INITIAL_WINDOW_SIZE] = |
+ SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size); |
+ scoped_ptr<SpdyFrame> initial_settings_frame( |
+ spdy_util_.ConstructSpdySettings(initial_settings)); |
+ scoped_ptr<SpdyFrame> initial_window_update( |
+ spdy_util_.ConstructSpdyWindowUpdate( |
+ kSessionFlowControlStreamId, |
+ session_max_recv_window_size - default_initial_window_size)); |
scoped_ptr<SpdyFrame> req( |
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); |
scoped_ptr<SpdyFrame> session_window_update( |
- spdy_util_.ConstructSpdyWindowUpdate(0, kTargetSize)); |
- scoped_ptr<SpdyFrame> window_update( |
- spdy_util_.ConstructSpdyWindowUpdate(1, kTargetSize)); |
+ spdy_util_.ConstructSpdyWindowUpdate(0, session_window_update_delta)); |
+ scoped_ptr<SpdyFrame> stream_window_update( |
+ spdy_util_.ConstructSpdyWindowUpdate(1, stream_window_update_delta)); |
std::vector<MockWrite> writes; |
+ if ((GetParam().protocol >= kProtoSPDY4MinimumVersion) && |
+ (GetParam().protocol <= kProtoSPDY4MaximumVersion)) { |
+ writes.push_back(MockWrite(ASYNC, kHttp2ConnectionHeaderPrefix, |
+ kHttp2ConnectionHeaderPrefixSize, 0)); |
+ } |
+ writes.push_back(CreateMockWrite(*initial_settings_frame)); |
+ writes.push_back(CreateMockWrite(*initial_window_update)); |
writes.push_back(CreateMockWrite(*req)); |
- if (GetParam().protocol >= kProtoSPDY31) |
- writes.push_back(CreateMockWrite(*session_window_update)); |
- writes.push_back(CreateMockWrite(*window_update)); |
+ writes.push_back(CreateMockWrite(*session_window_update)); |
+ writes.push_back(CreateMockWrite(*stream_window_update)); |
std::vector<MockRead> reads; |
scoped_ptr<SpdyFrame> resp( |
@@ -6172,7 +6203,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { |
reads.push_back(CreateMockRead(*resp)); |
ScopedVector<SpdyFrame> body_frames; |
- const std::string body_data(4096, 'x'); |
+ const std::string body_data(kChunkSize, 'x'); |
for (size_t remaining = kTargetSize; remaining != 0;) { |
size_t frame_size = std::min(remaining, body_data.size()); |
body_frames.push_back(spdy_util_.ConstructSpdyBodyFrame( |
@@ -6182,15 +6213,21 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { |
} |
reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 0)); // Yield. |
- DelayedSocketData data(1, vector_as_array(&reads), reads.size(), |
+ DelayedSocketData data(2, vector_as_array(&reads), reads.size(), |
vector_as_array(&writes), writes.size()); |
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY, |
BoundNetLog(), GetParam(), NULL); |
helper.AddData(&data); |
helper.RunPreTestSetup(); |
- HttpNetworkTransaction* trans = helper.trans(); |
+ SpdySessionPool* spdy_session_pool = helper.session()->spdy_session_pool(); |
+ SpdySessionPoolPeer pool_peer(spdy_session_pool); |
+ pool_peer.SetEnableSendingInitialData(true); |
+ pool_peer.SetSessionMaxRecvWindowSize(session_max_recv_window_size); |
+ pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size); |
+ |
+ HttpNetworkTransaction* trans = helper.trans(); |
TestCompletionCallback callback; |
int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |
@@ -6204,7 +6241,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { |
ASSERT_TRUE(stream->stream() != NULL); |
// All data has been read, but not consumed. The window reflects this. |
- EXPECT_EQ(static_cast<int>(initial_window_size - kTargetSize), |
+ EXPECT_EQ(static_cast<int>(stream_max_recv_window_size - kTargetSize), |
stream->stream()->recv_window_size()); |
const HttpResponseInfo* response = trans->GetResponseInfo(); |
@@ -6218,7 +6255,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateSent) { |
scoped_refptr<IOBuffer> buf(new IOBuffer(kTargetSize)); |
EXPECT_EQ(static_cast<int>(kTargetSize), |
trans->Read(buf.get(), kTargetSize, CompletionCallback())); |
- EXPECT_EQ(static_cast<int>(initial_window_size), |
+ EXPECT_EQ(static_cast<int>(stream_max_recv_window_size), |
stream->stream()->recv_window_size()); |
EXPECT_THAT(base::StringPiece(buf->data(), kTargetSize), Each(Eq('x'))); |