diff options
-rw-r--r-- | net/spdy/spdy_session_spdy3_unittest.cc | 216 | ||||
-rw-r--r-- | net/spdy/spdy_stream_spdy3_unittest.cc | 138 | ||||
-rw-r--r-- | net/spdy/spdy_stream_test_util.cc | 5 | ||||
-rw-r--r-- | net/spdy/spdy_stream_test_util.h | 1 |
4 files changed, 170 insertions, 190 deletions
diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_spdy3_unittest.cc index 6beeaa6..fa54b16 100644 --- a/net/spdy/spdy_session_spdy3_unittest.cc +++ b/net/spdy/spdy_session_spdy3_unittest.cc @@ -197,7 +197,8 @@ class SpdySessionSpdy3Test : public PlatformTest { void RunResumeAfterUnstallTest31( const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, - const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_fn); + const base::Callback<void(SpdySession*, SpdyStream*, int32)>& + unstall_function); // Original socket limits. Some tests set these. Safest to always restore // them once each test has been run. @@ -2914,7 +2915,8 @@ TEST_F(SpdySessionSpdy3Test, SessionFlowControlEndToEnd31) { // sure that a stream resumes after unstall. void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( const base::Callback<void(SpdySession*, SpdyStream*)>& stall_fn, - const base::Callback<void(SpdySession*, SpdyStream*, int32)>& unstall_fn) { + const base::Callback<void(SpdySession*, SpdyStream*, int32)>& + unstall_function) { const char kStreamUrl[] = "http://www.google.com/"; GURL url(kStreamUrl); @@ -2927,21 +2929,20 @@ void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); - scoped_ptr<SpdyFrame> msg( + scoped_ptr<SpdyFrame> body( ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req, 1), - CreateMockWrite(*msg, 3), + CreateMockWrite(*body, 2), }; scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> echo( ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*echo, 4), - MockRead(ASYNC, 0, 0, 5), // EOF + CreateMockRead(*resp, 3), + MockRead(ASYNC, 0, 0, 4), // EOF }; DeterministicSocketData data(reads, arraysize(reads), @@ -2972,19 +2973,17 @@ void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( EXPECT_TRUE(stream->HasUrl()); EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); - - data.RunFor(3); - EXPECT_FALSE(stream->send_stalled_by_flow_control()); + EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); + stall_fn.Run(session, stream); - EXPECT_EQ(ERR_IO_PENDING, delegate.OnSendBody()); + data.RunFor(2); EXPECT_TRUE(stream->send_stalled_by_flow_control()); - unstall_fn.Run(session, stream, kBodyDataSize); + unstall_function.Run(session, stream, kBodyDataSize); EXPECT_FALSE(stream->send_stalled_by_flow_control()); @@ -2995,7 +2994,7 @@ void SpdySessionSpdy3Test::RunResumeAfterUnstallTest31( EXPECT_TRUE(delegate.send_headers_completed()); EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); - EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate.TakeReceivedData()); + EXPECT_EQ(std::string(), delegate.TakeReceivedData()); EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate.body_data_sent()); } @@ -3074,30 +3073,24 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req2( ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, MEDIUM, NULL, 0)); - scoped_ptr<SpdyFrame> msg1( - ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, false)); - scoped_ptr<SpdyFrame> msg2( + scoped_ptr<SpdyFrame> body1( ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); + scoped_ptr<SpdyFrame> body2( + ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), - CreateMockWrite(*req2, 3), - CreateMockWrite(*msg1, 5), - CreateMockWrite(*msg2, 7), + CreateMockWrite(*req2, 2), + CreateMockWrite(*body2, 3), + CreateMockWrite(*body1, 4), }; scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> echo1( - ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, false)); - scoped_ptr<SpdyFrame> echo2( - ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockRead reads[] = { - CreateMockRead(*resp1, 2), - CreateMockRead(*resp2, 4), - CreateMockRead(*echo1, 6), - CreateMockRead(*echo2, 8), - MockRead(ASYNC, 0, 0, 9), // EOF + CreateMockRead(*resp1, 5), + CreateMockRead(*resp2, 6), + MockRead(ASYNC, 0, 0, 7), // EOF }; DeterministicSocketData data(reads, arraysize(reads), @@ -3128,11 +3121,6 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { EXPECT_TRUE(stream1->HasUrl()); EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); - - data.RunFor(3); - EXPECT_EQ(1u, stream1->stream_id()); - base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(session, url, MEDIUM, BoundNetLog()); ASSERT_TRUE(stream2.get() != NULL); @@ -3147,20 +3135,21 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { EXPECT_TRUE(stream2->HasUrl()); EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); - - data.RunFor(2); - EXPECT_EQ(3u, stream2->stream_id()); - EXPECT_FALSE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); StallSessionSend(session); - EXPECT_EQ(ERR_IO_PENDING, delegate1.OnSendBody()); - EXPECT_EQ(ERR_IO_PENDING, delegate2.OnSendBody()); + EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); + data.RunFor(2); + EXPECT_EQ(1u, stream1->stream_id()); EXPECT_TRUE(stream1->send_stalled_by_flow_control()); + + EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); + + data.RunFor(1); + EXPECT_EQ(3u, stream2->stream_id()); EXPECT_TRUE(stream2->send_stalled_by_flow_control()); // This should unstall only stream2. @@ -3169,7 +3158,7 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { EXPECT_TRUE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); - data.RunFor(2); + data.RunFor(1); EXPECT_TRUE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); @@ -3180,7 +3169,7 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { EXPECT_FALSE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); - data.RunFor(3); + data.RunFor(4); EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate1.WaitForClose()); EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); @@ -3188,13 +3177,13 @@ TEST_F(SpdySessionSpdy3Test, ResumeByPriorityAfterSendWindowSizeIncrease31) { EXPECT_TRUE(delegate1.send_headers_completed()); EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); - EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate1.TakeReceivedData()); + EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate1.body_data_sent()); EXPECT_TRUE(delegate2.send_headers_completed()); EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); - EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.TakeReceivedData()); + EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); } @@ -3243,27 +3232,20 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req3( ConstructSpdyPost(kStreamUrl, 5, kBodyDataSize, LOWEST, NULL, 0)); - scoped_ptr<SpdyFrame> msg2( + scoped_ptr<SpdyFrame> body2( ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), - CreateMockWrite(*req2, 3), - CreateMockWrite(*req3, 5), - CreateMockWrite(*msg2, 7), + CreateMockWrite(*req2, 2), + CreateMockWrite(*req3, 3), + CreateMockWrite(*body2, 4), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> resp3(ConstructSpdyGetSynReply(NULL, 0, 5)); - scoped_ptr<SpdyFrame> echo2( - ConstructSpdyBodyFrame(3, kBodyData, kBodyDataSize, false)); MockRead reads[] = { - CreateMockRead(*resp1, 2), - CreateMockRead(*resp2, 4), - CreateMockRead(*resp3, 6), - CreateMockRead(*echo2, 8), - MockRead(ASYNC, 0, 0, 9), // EOF + CreateMockRead(*resp2, 5), + MockRead(ASYNC, 0, 0, 6), // EOF }; DeterministicSocketData data(reads, arraysize(reads), @@ -3294,11 +3276,6 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { EXPECT_TRUE(stream1->HasUrl()); EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); - - data.RunFor(3); - EXPECT_EQ(1u, stream1->stream_id()); - base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(session, url, LOWEST, BoundNetLog()); ASSERT_TRUE(stream2.get() != NULL); @@ -3313,11 +3290,6 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { EXPECT_TRUE(stream2->HasUrl()); EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); - - data.RunFor(2); - EXPECT_EQ(3u, stream2->stream_id()); - base::WeakPtr<SpdyStream> stream3 = CreateStreamSynchronously(session, url, LOWEST, BoundNetLog()); ASSERT_TRUE(stream3.get() != NULL); @@ -3332,23 +3304,28 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { EXPECT_TRUE(stream3->HasUrl()); EXPECT_EQ(kStreamUrl, stream3->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream3->SendRequest(true)); - - data.RunFor(2); - EXPECT_EQ(5u, stream3->stream_id()); - EXPECT_FALSE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); EXPECT_FALSE(stream3->send_stalled_by_flow_control()); StallSessionSend(session); - EXPECT_EQ(ERR_IO_PENDING, delegate1.OnSendBody()); - EXPECT_EQ(ERR_IO_PENDING, delegate2.OnSendBody()); - EXPECT_EQ(ERR_IO_PENDING, delegate3.OnSendBody()); + EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); + data.RunFor(2); + EXPECT_EQ(1u, stream1->stream_id()); EXPECT_TRUE(stream1->send_stalled_by_flow_control()); + + EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); + + data.RunFor(1); + EXPECT_EQ(3u, stream2->stream_id()); EXPECT_TRUE(stream2->send_stalled_by_flow_control()); + + EXPECT_EQ(ERR_IO_PENDING, stream3->SendRequest(true)); + + data.RunFor(1); + EXPECT_EQ(5u, stream3->stream_id()); EXPECT_TRUE(stream3->send_stalled_by_flow_control()); SpdyStreamId stream_id1 = stream1->stream_id(); @@ -3381,57 +3358,20 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedStreams31) { EXPECT_EQ(OK, delegate3.WaitForClose()); EXPECT_TRUE(delegate1.send_headers_completed()); - EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); - EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); EXPECT_EQ(0, delegate1.body_data_sent()); EXPECT_TRUE(delegate2.send_headers_completed()); EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); - EXPECT_EQ(kBodyDataStringPiece.as_string(), delegate2.TakeReceivedData()); + EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); EXPECT_EQ(static_cast<int>(kBodyDataSize), delegate2.body_data_sent()); EXPECT_TRUE(delegate3.send_headers_completed()); - EXPECT_EQ("200", delegate3.GetResponseHeaderValue(":status")); - EXPECT_EQ("HTTP/1.1", delegate3.GetResponseHeaderValue(":version")); EXPECT_EQ(std::string(), delegate3.TakeReceivedData()); EXPECT_EQ(0, delegate3.body_data_sent()); } -// Delegate that closes a given session after sending its body. -class SessionClosingDelegate : public test::StreamDelegateWithBody { - public: - SessionClosingDelegate(const base::WeakPtr<SpdyStream>& stream, - base::StringPiece data) - : StreamDelegateWithBody(stream, data) {} - - virtual ~SessionClosingDelegate() {} - - void set_session_to_close( - const scoped_refptr<SpdySession>& session_to_close) { - session_to_close_ = session_to_close; - } - - virtual int OnSendBody() OVERRIDE { - int rv = test::StreamDelegateWithBody::OnSendBody(); - if (session_to_close_) { - MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&SpdySession::CloseSessionOnError, - session_to_close_, - ERR_CONNECTION_CLOSED, - true, - "Closed by SessionClosingDelegate")); - session_to_close_ = NULL; - } - return rv; - } - - private: - scoped_refptr<SpdySession> session_to_close_; -}; - // Cause a stall by reducing the flow control send window to // 0. Unstalling the session should properly handle the session itself // being closed. @@ -3450,21 +3390,16 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { ConstructSpdyPost(kStreamUrl, 1, kBodyDataSize, LOWEST, NULL, 0)); scoped_ptr<SpdyFrame> req2( ConstructSpdyPost(kStreamUrl, 3, kBodyDataSize, LOWEST, NULL, 0)); - scoped_ptr<SpdyFrame> msg1( + scoped_ptr<SpdyFrame> body1( ConstructSpdyBodyFrame(1, kBodyData, kBodyDataSize, false)); MockWrite writes[] = { CreateMockWrite(*initial_window_update, 0), CreateMockWrite(*req1, 1), - CreateMockWrite(*req2, 3), - CreateMockWrite(*msg1, 5), + CreateMockWrite(*req2, 2), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); MockRead reads[] = { - CreateMockRead(*resp1, 2), - CreateMockRead(*resp2, 4), - MockRead(ASYNC, 0, 0, 6), // EOF + MockRead(ASYNC, 0, 0, 3), // EOF }; DeterministicSocketData data(reads, arraysize(reads), @@ -3485,7 +3420,7 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { CreateStreamSynchronously(session, url, LOWEST, BoundNetLog()); ASSERT_TRUE(stream1.get() != NULL); - SessionClosingDelegate delegate1(stream1, kBodyDataStringPiece); + test::StreamDelegateWithBody delegate1(stream1, kBodyDataStringPiece); stream1->SetDelegate(&delegate1); EXPECT_FALSE(stream1->HasUrl()); @@ -3495,11 +3430,6 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { EXPECT_TRUE(stream1->HasUrl()); EXPECT_EQ(kStreamUrl, stream1->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); - - data.RunFor(3); - EXPECT_EQ(1u, stream1->stream_id()); - base::WeakPtr<SpdyStream> stream2 = CreateStreamSynchronously(session, url, LOWEST, BoundNetLog()); ASSERT_TRUE(stream2.get() != NULL); @@ -3514,32 +3444,32 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { EXPECT_TRUE(stream2->HasUrl()); EXPECT_EQ(kStreamUrl, stream2->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); - - data.RunFor(2); - EXPECT_EQ(3u, stream2->stream_id()); - EXPECT_FALSE(stream1->send_stalled_by_flow_control()); EXPECT_FALSE(stream2->send_stalled_by_flow_control()); StallSessionSend(session); - EXPECT_EQ(ERR_IO_PENDING, delegate1.OnSendBody()); - EXPECT_EQ(ERR_IO_PENDING, delegate2.OnSendBody()); + EXPECT_EQ(ERR_IO_PENDING, stream1->SendRequest(true)); + data.RunFor(2); + EXPECT_EQ(1u, stream1->stream_id()); EXPECT_TRUE(stream1->send_stalled_by_flow_control()); + + EXPECT_EQ(ERR_IO_PENDING, stream2->SendRequest(true)); + + data.RunFor(1); + EXPECT_EQ(3u, stream2->stream_id()); EXPECT_TRUE(stream2->send_stalled_by_flow_control()); EXPECT_TRUE(spdy_session_pool_->HasSession(key_)); - // Unstall stream1, which should then post a task to close the - // session. - delegate1.set_session_to_close(session); + // Unstall stream1. UnstallSessionSend(session, kBodyDataSize); - session = NULL; - // Run the task to close the session. - MessageLoop::current()->RunUntilIdle(); + // Close the session (since we can't do it from within the delegate + // method, since it's in the stream's loop). + session->CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "Closing session"); + session = NULL; EXPECT_FALSE(spdy_session_pool_->HasSession(key_)); @@ -3547,14 +3477,10 @@ TEST_F(SpdySessionSpdy3Test, SendWindowSizeIncreaseWithDeletedSession31) { EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate2.WaitForClose()); EXPECT_TRUE(delegate1.send_headers_completed()); - EXPECT_EQ("200", delegate1.GetResponseHeaderValue(":status")); - EXPECT_EQ("HTTP/1.1", delegate1.GetResponseHeaderValue(":version")); EXPECT_EQ(std::string(), delegate1.TakeReceivedData()); EXPECT_EQ(0, delegate1.body_data_sent()); EXPECT_TRUE(delegate2.send_headers_completed()); - EXPECT_EQ("200", delegate2.GetResponseHeaderValue(":status")); - EXPECT_EQ("HTTP/1.1", delegate2.GetResponseHeaderValue(":version")); EXPECT_EQ(std::string(), delegate2.TakeReceivedData()); EXPECT_EQ(0, delegate2.body_data_sent()); } diff --git a/net/spdy/spdy_stream_spdy3_unittest.cc b/net/spdy/spdy_stream_spdy3_unittest.cc index 2c80211..f009043 100644 --- a/net/spdy/spdy_stream_spdy3_unittest.cc +++ b/net/spdy/spdy_stream_spdy3_unittest.cc @@ -5,6 +5,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string_piece.h" #include "net/base/completion_callback.h" #include "net/base/net_log_unittest.h" @@ -38,6 +39,11 @@ const base::StringPiece kPostBodyStringPiece(kPostBody, kPostBodyLength); class SpdyStreamSpdy3Test : public testing::Test { protected: + // A function that takes a SpdyStream and the number of bytes which + // will unstall the next frame completely. + typedef base::Callback<void(const base::WeakPtr<SpdyStream>&, int32)> + UnstallFunction; + SpdyStreamSpdy3Test() : spdy_util_(kProtoSPDY3), host_port_pair_("www.google.com", 80), @@ -70,6 +76,12 @@ class SpdyStreamSpdy3Test : public testing::Test { MessageLoop::current()->RunUntilIdle(); } + void RunResumeAfterUnstallRequestResponseTest( + const UnstallFunction& unstall_function); + + void RunResumeAfterUnstallBidirectionalTest( + const UnstallFunction& unstall_function); + SpdyTestUtil spdy_util_; HostPortPair host_port_pair_; SpdySessionDependencies session_deps_; @@ -416,9 +428,41 @@ TEST_F(SpdyStreamSpdy3Test, IncreaseSendWindowSizeOverflow) { EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, delegate.WaitForClose()); } -// Cause a send stall by reducing the flow control send window to -// 0. The stream should resume when that window is then increased. -TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncrease) { +// Functions used with +// RunResumeAfterUnstall{RequestResponse,Bidirectional}Test(). + +void StallStream(const base::WeakPtr<SpdyStream>& stream) { + // Reduce the send window size to 0 to stall. + while (stream->send_window_size() > 0) { + stream->DecreaseSendWindowSize( + std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); + } +} + +void IncreaseStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream, + int32 delta_window_size) { + EXPECT_TRUE(stream->send_stalled_by_flow_control()); + stream->IncreaseSendWindowSize(delta_window_size); + EXPECT_FALSE(stream->send_stalled_by_flow_control()); +} + +void AdjustStreamSendWindowSize(const base::WeakPtr<SpdyStream>& stream, + int32 delta_window_size) { + // Make sure that negative adjustments are handled properly. + EXPECT_TRUE(stream->send_stalled_by_flow_control()); + stream->AdjustSendWindowSize(-delta_window_size); + EXPECT_TRUE(stream->send_stalled_by_flow_control()); + stream->AdjustSendWindowSize(+delta_window_size); + EXPECT_TRUE(stream->send_stalled_by_flow_control()); + stream->AdjustSendWindowSize(+delta_window_size); + EXPECT_FALSE(stream->send_stalled_by_flow_control()); +} + +// Given an unstall function, runs a test to make sure that a +// request/response (i.e., an HTTP-like) stream resumes after a stall +// and unstall. +void SpdyStreamSpdy3Test::RunResumeAfterUnstallRequestResponseTest( + const UnstallFunction& unstall_function) { GURL url(kStreamUrl); session_ = @@ -426,20 +470,17 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncrease) { scoped_ptr<SpdyFrame> req( ConstructSpdyPost(kStreamUrl, 1, kPostBodyLength, LOWEST, NULL, 0)); - scoped_ptr<SpdyFrame> msg( + scoped_ptr<SpdyFrame> body( ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); MockWrite writes[] = { CreateMockWrite(*req, 0), - CreateMockWrite(*msg, 2), + CreateMockWrite(*body, 1), }; scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> echo( - ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false)); MockRead reads[] = { - CreateMockRead(*resp, 1), - CreateMockRead(*echo, 3), - MockRead(ASYNC, 0, 0, 4), // EOF + CreateMockRead(*resp, 2), + MockRead(ASYNC, 0, 0, 3), // EOF }; DeterministicSocketData data(reads, arraysize(reads), @@ -467,23 +508,17 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncrease) { EXPECT_TRUE(stream->HasUrl()); EXPECT_EQ(kStreamUrl, stream->GetUrl().spec()); - EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); - - data.RunFor(2); - EXPECT_FALSE(stream->send_stalled_by_flow_control()); - // Reduce the send window size to 0 to stall. - while (stream->send_window_size() > 0) { - stream->DecreaseSendWindowSize( - std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); - } + EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); - EXPECT_EQ(ERR_IO_PENDING, delegate.OnSendBody()); + StallStream(stream); + + data.RunFor(1); EXPECT_TRUE(stream->send_stalled_by_flow_control()); - stream->IncreaseSendWindowSize(kPostBodyLength); + unstall_function.Run(stream, kPostBodyLength); EXPECT_FALSE(stream->send_stalled_by_flow_control()); @@ -494,15 +529,25 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncrease) { EXPECT_TRUE(delegate.send_headers_completed()); EXPECT_EQ("200", delegate.GetResponseHeaderValue(":status")); EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); - EXPECT_EQ(std::string(kPostBody, kPostBodyLength), - delegate.TakeReceivedData()); + EXPECT_EQ(std::string(), delegate.TakeReceivedData()); EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.body_data_sent()); } -// Cause a send stall by reducing the flow control send window to -// 0. The stream should resume when that window is then adjusted -// positively. -TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjust) { +TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeIncreaseRequestResponse) { + RunResumeAfterUnstallRequestResponseTest( + base::Bind(&IncreaseStreamSendWindowSize)); +} + +TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjustRequestResponse) { + RunResumeAfterUnstallRequestResponseTest( + base::Bind(&AdjustStreamSendWindowSize)); +} + +// Given an unstall function, runs a test to make sure that a +// bidrectional (i.e., non-HTTP-like) stream resumes after a stall and +// unstall. +void SpdyStreamSpdy3Test::RunResumeAfterUnstallBidirectionalTest( + const UnstallFunction& unstall_function) { GURL url(kStreamUrl); session_ = @@ -541,7 +586,8 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjust) { CreateStreamSynchronously(session, url, LOWEST, BoundNetLog()); ASSERT_TRUE(stream.get() != NULL); - StreamDelegateWithBody delegate(stream, kPostBodyStringPiece); + StreamDelegateSendImmediate delegate(stream, scoped_ptr<SpdyHeaderBlock>(), + kPostBodyStringPiece); stream->SetDelegate(&delegate); EXPECT_FALSE(stream->HasUrl()); @@ -553,29 +599,17 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjust) { EXPECT_EQ(ERR_IO_PENDING, stream->SendRequest(true)); - data.RunFor(2); + data.RunFor(1); EXPECT_FALSE(stream->send_stalled_by_flow_control()); - // Reduce the send window size to 0 to stall. - while (stream->send_window_size() > 0) { - stream->DecreaseSendWindowSize( - std::min(kMaxSpdyFrameChunkSize, stream->send_window_size())); - } - - EXPECT_EQ(ERR_IO_PENDING, delegate.OnSendBody()); + StallStream(stream); - EXPECT_TRUE(stream->send_stalled_by_flow_control()); - - stream->AdjustSendWindowSize(-static_cast<int>(kPostBodyLength)); - - EXPECT_TRUE(stream->send_stalled_by_flow_control()); - - stream->AdjustSendWindowSize(kPostBodyLength); + data.RunFor(1); EXPECT_TRUE(stream->send_stalled_by_flow_control()); - stream->AdjustSendWindowSize(kPostBodyLength); + unstall_function.Run(stream, kPostBodyLength); EXPECT_FALSE(stream->send_stalled_by_flow_control()); @@ -588,7 +622,21 @@ TEST_F(SpdyStreamSpdy3Test, ResumeAfterSendWindowSizeAdjust) { EXPECT_EQ("HTTP/1.1", delegate.GetResponseHeaderValue(":version")); EXPECT_EQ(std::string(kPostBody, kPostBodyLength), delegate.TakeReceivedData()); - EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.body_data_sent()); + EXPECT_EQ(static_cast<int>(kPostBodyLength), delegate.data_sent()); +} + +// TODO(akalin): Re-enable these when http://crbug.com/242288 is +// fixed. +TEST_F(SpdyStreamSpdy3Test, + DISABLED_ResumeAfterSendWindowSizeIncreaseBidirectional) { + RunResumeAfterUnstallBidirectionalTest( + base::Bind(&IncreaseStreamSendWindowSize)); +} + +TEST_F(SpdyStreamSpdy3Test, + DISABLED_ResumeAfterSendWindowSizeAdjustBidirectional) { + RunResumeAfterUnstallBidirectionalTest( + base::Bind(&AdjustStreamSendWindowSize)); } } // namespace diff --git a/net/spdy/spdy_stream_test_util.cc b/net/spdy/spdy_stream_test_util.cc index 76597ab..b434f3e 100644 --- a/net/spdy/spdy_stream_test_util.cc +++ b/net/spdy/spdy_stream_test_util.cc @@ -187,6 +187,11 @@ StreamDelegateWithBody::StreamDelegateWithBody( StreamDelegateWithBody::~StreamDelegateWithBody() { } +SpdySendStatus StreamDelegateWithBody::OnSendHeadersComplete() { + StreamDelegateBase::OnSendHeadersComplete(); + return MORE_DATA_TO_SEND; +} + int StreamDelegateWithBody::OnSendBody() { stream()->QueueStreamData(buf_.get(), buf_->BytesRemaining(), DATA_FLAG_NONE); diff --git a/net/spdy/spdy_stream_test_util.h b/net/spdy/spdy_stream_test_util.h index baf92a1..2dacb63 100644 --- a/net/spdy/spdy_stream_test_util.h +++ b/net/spdy/spdy_stream_test_util.h @@ -134,6 +134,7 @@ class StreamDelegateWithBody : public StreamDelegateBase { base::StringPiece data); virtual ~StreamDelegateWithBody(); + virtual SpdySendStatus OnSendHeadersComplete() OVERRIDE; virtual int OnSendBody() OVERRIDE; virtual SpdySendStatus OnSendBodyComplete(size_t bytes_sent) OVERRIDE; |