Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(691)

Unified Diff: net/spdy/spdy_stream_unittest.cc

Issue 2526003002: Disallow multiple HEADERS frames on pushed streams. (Closed)
Patch Set: Rename enum, enum entry, and member. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_stream_unittest.cc
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index 53452bed815728c3daa08c97c6a7fd93b0a9e5c7..64d0f8e0ffdd030d03d3112c1297ae0d2b1a21a7 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -553,8 +553,8 @@ TEST_F(SpdyStreamTest, UpperCaseHeaders) {
AddWrite(req);
const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
- SpdySerializedFrame reply(
- spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1));
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(
+ kExtraHeaders, arraysize(kExtraHeaders) / 2, 1));
AddRead(reply);
SpdySerializedFrame rst(
@@ -589,6 +589,9 @@ TEST_F(SpdyStreamTest, UpperCaseHeaders) {
EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
// Receiving a header with uppercase ASCII should result in a protocol error
@@ -601,9 +604,9 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(reply);
- const char* const extra_headers[] = {"X-UpperCase", "yes"};
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(extra_headers, 1, 2, 1, kPushUrl));
+ const char* const kExtraHeaders[] = {"X-UpperCase", "yes"};
+ SpdySerializedFrame push(spdy_util_.ConstructSpdyPush(
+ kExtraHeaders, arraysize(kExtraHeaders) / 2, 2, 1, kPushUrl));
AddRead(push);
SpdySerializedFrame rst(
@@ -650,36 +653,92 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersOnPush) {
data.Resume();
EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
-// Receiving a header with uppercase ASCII in a HEADERS frame should result in a
-// protocol error.
-TEST_F(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
+TEST_F(SpdyStreamTest, HeadersMustHaveStatus) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(req);
- SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ // Response headers without ":status" header field: protocol error.
+ SpdyHeaderBlock header_block_without_status;
+ header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
+ header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
+ header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
+ header_block_without_status[spdy_util_.GetPathKey()] = "/";
+ SpdySerializedFrame reply(
+ spdy_util_.ConstructSpdyReply(1, std::move(header_block_without_status)));
AddRead(reply);
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl));
- AddRead(push);
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
- AddReadPause();
+ AddReadEOF();
- SpdyHeaderBlock late_headers;
- late_headers["X-UpperCase"] = "yes";
- SpdySerializedFrame headers_frame(
- spdy_util_.ConstructSpdyReply(2, std::move(late_headers)));
- AddRead(headers_frame);
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
- AddWritePause();
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, HeadersMustHaveStatusOnPushedStream) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
+
+ SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
+ spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
+ AddRead(push_promise);
+
+ // Response headers without ":status" header field: protocol error.
+ SpdyHeaderBlock header_block_without_status;
+ header_block_without_status[spdy_util_.GetMethodKey()] = "GET";
+ header_block_without_status[spdy_util_.GetHostKey()] = "www.example.org";
+ header_block_without_status[spdy_util_.GetSchemeKey()] = "https";
+ header_block_without_status[spdy_util_.GetPathKey()] = "/";
+ SpdySerializedFrame pushed_reply(
+ spdy_util_.ConstructSpdyReply(2, std::move(header_block_without_status)));
+ AddRead(pushed_reply);
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(rst);
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
AddReadEOF();
SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
@@ -707,30 +766,59 @@ TEST_F(SpdyStreamTest, UpperCaseHeadersInHeadersFrame) {
IsError(ERR_IO_PENDING));
EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
- data.RunUntilPaused();
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
- base::WeakPtr<SpdyStream> push_stream;
- EXPECT_THAT(
- session->GetPushStream(GURL(kPushUrl), &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_TRUE(push_stream);
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
- data.Resume();
- data.RunUntilPaused();
+TEST_F(SpdyStreamTest, HeadersMustPreceedData) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
- EXPECT_THAT(
- session->GetPushStream(GURL(kPushUrl), &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_FALSE(push_stream);
+ // Response body not preceeded by headers: protocol error.
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
- data.Resume();
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
}
-// Receiving a duplicate header in a HEADERS frame should result in a protocol
-// error.
-TEST_F(SpdyStreamTest, DuplicateHeaders) {
+TEST_F(SpdyStreamTest, HeadersMustPreceedDataOnPushedStream) {
SpdySerializedFrame req(
spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
AddWrite(req);
@@ -738,24 +826,22 @@ TEST_F(SpdyStreamTest, DuplicateHeaders) {
SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
AddRead(reply);
- SpdySerializedFrame push(
- spdy_util_.ConstructSpdyPush(nullptr, 0, 2, 1, kPushUrl));
- AddRead(push);
-
- AddReadPause();
-
- SpdyHeaderBlock late_headers;
- late_headers[spdy_util_.GetStatusKey()] = "500 Server Error";
- SpdySerializedFrame headers_frame(
- spdy_util_.ConstructSpdyReply(2, std::move(late_headers)));
- AddRead(headers_frame);
+ SpdySerializedFrame push_promise(spdy_util_.ConstructInitialSpdyPushFrame(
+ spdy_util_.ConstructGetHeaderBlock(kPushUrl), 2, 1));
+ AddRead(push_promise);
- AddReadPause();
+ SpdySerializedFrame pushed_body(
+ spdy_util_.ConstructSpdyDataFrame(2, kPostBody, kPostBodyLength, true));
+ AddRead(pushed_body);
SpdySerializedFrame rst(
spdy_util_.ConstructSpdyRstStream(2, RST_STREAM_PROTOCOL_ERROR));
AddWrite(rst);
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, true));
+ AddRead(body);
+
AddReadEOF();
SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
@@ -783,25 +869,129 @@ TEST_F(SpdyStreamTest, DuplicateHeaders) {
IsError(ERR_IO_PENDING));
EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
- data.RunUntilPaused();
+ EXPECT_THAT(delegate.WaitForClose(), IsOk());
+ EXPECT_EQ("200", delegate.GetResponseHeaderValue(spdy_util_.GetStatusKey()));
+ EXPECT_EQ(std::string(kPostBody, kPostBodyLength),
+ delegate.TakeReceivedData());
- base::WeakPtr<SpdyStream> push_stream;
- EXPECT_THAT(
- session->GetPushStream(GURL(kPushUrl), &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_TRUE(push_stream);
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
- data.Resume();
- data.RunUntilPaused();
+TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
- EXPECT_THAT(
- session->GetPushStream(GURL(kPushUrl), &push_stream, NetLogWithSource()),
- IsOk());
- EXPECT_FALSE(push_stream);
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
- data.Resume();
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
+ AddRead(body);
- EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_CONNECTION_CLOSED));
+ SpdyHeaderBlock trailers_block;
+ trailers_block["foo"] = "bar";
+ SpdySerializedFrame first_trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), false));
+ AddRead(first_trailers);
+
+ // Trailers following trailers: procotol error.
+ SpdySerializedFrame second_trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), true));
+ AddRead(second_trailers);
+
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) {
+ SpdySerializedFrame req(
+ spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST, true));
+ AddWrite(req);
+
+ SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
+ AddRead(reply);
+
+ SpdySerializedFrame body(
+ spdy_util_.ConstructSpdyDataFrame(1, kPostBody, kPostBodyLength, false));
+ AddRead(body);
+
+ SpdyHeaderBlock trailers_block;
+ trailers_block["foo"] = "bar";
+ SpdySerializedFrame trailers(spdy_util_.ConstructSpdyResponseHeaders(
+ 1, std::move(trailers_block), false));
+ AddRead(trailers);
+
+ // DATA frame following trailers: protocol error.
+ AddRead(body);
+
+ SpdySerializedFrame rst(
+ spdy_util_.ConstructSpdyRstStream(1, RST_STREAM_PROTOCOL_ERROR));
+ AddWrite(rst);
+
+ AddReadEOF();
+
+ SequencedSocketData data(GetReads(), GetNumReads(), GetWrites(),
+ GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+
+ AddSSLSocketData();
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url_, LOWEST, NetLogWithSource());
+ ASSERT_TRUE(stream);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_TRUE(stream->GetUrlFromHeaders().is_empty());
+
+ SpdyHeaderBlock headers(spdy_util_.ConstructGetHeaderBlock(kDefaultUrl));
+ EXPECT_EQ(ERR_IO_PENDING, stream->SendRequestHeaders(std::move(headers),
+ NO_MORE_DATA_TO_SEND));
+ EXPECT_EQ(kDefaultUrl, stream->GetUrlFromHeaders().spec());
+
+ EXPECT_THAT(delegate.WaitForClose(), IsError(ERR_SPDY_PROTOCOL_ERROR));
+
+ EXPECT_TRUE(data.AllWriteDataConsumed());
+ EXPECT_TRUE(data.AllReadDataConsumed());
}
// Call IncreaseSendWindowSize on a stream with a large enough delta to overflow
« no previous file with comments | « net/spdy/spdy_stream_test_util.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698