summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-22 07:49:56 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-22 07:49:56 +0000
commitd2de7da44ba26757417be01996d966013ff62ffd (patch)
tree844b71899c0f8aae93111e7935c856e73c2b63d7
parent76af173df21260cd16aaa05a2a804ae84551c17b (diff)
downloadchromium_src-d2de7da44ba26757417be01996d966013ff62ffd.zip
chromium_src-d2de7da44ba26757417be01996d966013ff62ffd.tar.gz
chromium_src-d2de7da44ba26757417be01996d966013ff62ffd.tar.bz2
[SPDY] Rework SPDY flow control tests and add some for http://crbug.com/242288
Make most SPDY flow control tests simulate a request and a response. Add new tests for SPDY flow control with bidirectional (i.e., non-HTTP-like) streams. They're disabled for now until the bug below is actually fixed. Also refactor out some common code between SpdyStream flow control tests. BUG=242288 Review URL: https://chromiumcodereview.appspot.com/15411005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201466 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/spdy/spdy_session_spdy3_unittest.cc216
-rw-r--r--net/spdy/spdy_stream_spdy3_unittest.cc138
-rw-r--r--net/spdy/spdy_stream_test_util.cc5
-rw-r--r--net/spdy/spdy_stream_test_util.h1
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;