diff options
Diffstat (limited to 'net/spdy')
| -rw-r--r-- | net/spdy/buffered_spdy_framer.cc | 2 | ||||
| -rw-r--r-- | net/spdy/spdy_framer.cc | 18 | ||||
| -rw-r--r-- | net/spdy/spdy_framer.h | 5 | ||||
| -rw-r--r-- | net/spdy/spdy_framer_test.cc | 341 |
4 files changed, 341 insertions, 25 deletions
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index e76b83d..e7e3d3d 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc @@ -202,7 +202,7 @@ void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, } void BufferedSpdyFramer::OnStreamEnd(SpdyStreamId stream_id) { - LOG(DFATAL) << "Unimplemented"; + visitor_->OnStreamFrameData(stream_id, nullptr, 0, true); } void BufferedSpdyFramer::OnStreamPadding(SpdyStreamId stream_id, size_t len) { diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index e34345a..5c8d011 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc @@ -14,6 +14,7 @@ #include "base/lazy_instance.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram_macros.h" +#include "net/quic/quic_flags.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/spdy_frame_builder.h" #include "net/spdy/spdy_frame_reader.h" @@ -171,7 +172,8 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version) enable_compression_(true), syn_frame_processed_(false), probable_http_response_(false), - end_stream_when_done_(false) { + end_stream_when_done_(false), + spdy_on_stream_end_(FLAGS_spdy_on_stream_end) { DCHECK(protocol_version_ == SPDY3 || protocol_version_ == HTTP2); DCHECK_LE(kMaxControlFrameSize, SpdyConstants::GetFrameMaximumSize(protocol_version_) + @@ -830,8 +832,12 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { } else { // Empty data frame. if (current_frame_flags_ & DATA_FLAG_FIN) { - visitor_->OnStreamFrameData( - current_frame_stream_id_, NULL, 0, true); + if (spdy_on_stream_end_) { + visitor_->OnStreamEnd(current_frame_stream_id_); + } else { + visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0, + true); + } } CHANGE_STATE(SPDY_FRAME_COMPLETE); } @@ -2099,7 +2105,11 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 || end_stream_when_done_)) { end_stream_when_done_ = false; - visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); + if (spdy_on_stream_end_) { + visitor_->OnStreamEnd(current_frame_stream_id_); + } else { + visitor_->OnStreamFrameData(current_frame_stream_id_, nullptr, 0, true); + } } CHANGE_STATE(SPDY_FRAME_COMPLETE); } diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 30e7899..6261777 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h @@ -795,6 +795,11 @@ class NET_EXPORT_PRIVATE SpdyFramer { // If true, then ProcessInput returns after processing a full frame, // rather than reading all available input. bool process_single_input_frame_ = false; + + // Latched value of --FLAGS_spdy_on_stream_end. + // If true, OnStreamEnd will be called instead of the sentinel call of + // OnStreamFrameData(stream_id, nullptr, 0, true) + bool spdy_on_stream_end_; }; } // namespace net diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index 2dcc855..5e41327 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc @@ -16,6 +16,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "net/quic/quic_flags.h" #include "net/spdy/hpack/hpack_constants.h" #include "net/spdy/mock_spdy_framer_visitor.h" #include "net/spdy/spdy_frame_builder.h" @@ -281,7 +282,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, fin_frame_count_(0), fin_opaque_data_(), fin_flag_count_(0), - zero_length_data_frame_count_(0), + end_of_stream_count_(0), control_frame_header_data_count_(0), zero_length_control_frame_header_data_count_(0), data_frame_count_(0), @@ -312,8 +313,10 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, size_t len, bool fin) override { EXPECT_EQ(header_stream_id_, stream_id); - if (len == 0) { - ++zero_length_data_frame_count_; + if (!FLAGS_spdy_on_stream_end) { + if (len == 0) { + ++end_of_stream_count_; + } } data_bytes_ += len; @@ -328,7 +331,9 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, } void OnStreamEnd(SpdyStreamId stream_id) override { - LOG(DFATAL) << "Unimplemented."; + LOG(INFO) << "OnStreamEnd(" << stream_id << ")"; + EXPECT_EQ(header_stream_id_, stream_id); + ++end_of_stream_count_; } void OnStreamPadding(SpdyStreamId stream_id, size_t len) override { @@ -587,7 +592,7 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface, int fin_frame_count_; // The count of RST_STREAM type frames received. string fin_opaque_data_; int fin_flag_count_; // The count of frames with the FIN flag set. - int zero_length_data_frame_count_; // The count of zero-length data frames. + int end_of_stream_count_; // The count of zero-length data frames. int control_frame_header_data_count_; // The count of chunks received. // The count of zero-length control frame header data chunks received. int zero_length_control_frame_header_data_count_; @@ -1207,7 +1212,7 @@ TEST_P(SpdyFramerTest, Basic) { } EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_EQ(4, visitor.data_frame_count_); visitor.fin_opaque_data_.clear(); } @@ -1289,7 +1294,7 @@ TEST_P(SpdyFramerTest, FinOnDataFrame) { EXPECT_EQ(16, visitor.data_bytes_); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(2, visitor.data_frame_count_); } @@ -1348,7 +1353,7 @@ TEST_P(SpdyFramerTest, FinOnSynReplyFrame) { EXPECT_EQ(0, visitor.data_bytes_); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(1, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(0, visitor.data_frame_count_); } @@ -1466,7 +1471,7 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) { EXPECT_EQ(arraysize(bytes), static_cast<unsigned>(visitor.data_bytes_)); EXPECT_EQ(0, visitor.fin_frame_count_); EXPECT_EQ(0, visitor.fin_flag_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(1, visitor.data_frame_count_); } @@ -3196,7 +3201,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) { // at least twice. EXPECT_LE(2, visitor.control_frame_header_data_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_EQ(headers, visitor.headers_); } @@ -3221,7 +3226,7 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) { // at least twice. EXPECT_LE(2, visitor.control_frame_header_data_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_EQ(headers, visitor.headers_); } @@ -3258,7 +3263,7 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) { EXPECT_EQ(0, visitor.error_count_); EXPECT_EQ(1, visitor.syn_frame_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_LT(kBigValueSize, visitor.header_buffer_length_); } @@ -3403,7 +3408,7 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) { EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_); // The framer should not have sent half-close to the visitor. - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); } TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) { @@ -3860,7 +3865,7 @@ TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) { EXPECT_EQ(2, visitor.continuation_count_); EXPECT_EQ(1, visitor.fin_flag_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(1, visitor.zero_length_data_frame_count_); + EXPECT_EQ(1, visitor.end_of_stream_count_); EXPECT_THAT(visitor.headers_, testing::ElementsAre( @@ -3910,7 +3915,7 @@ TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) { EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_); EXPECT_EQ(2, visitor.continuation_count_); EXPECT_EQ(1, visitor.zero_length_control_frame_header_data_count_); - EXPECT_EQ(0, visitor.zero_length_data_frame_count_); + EXPECT_EQ(0, visitor.end_of_stream_count_); EXPECT_THAT(visitor.headers_, testing::ElementsAre( @@ -4384,6 +4389,50 @@ TEST_P(SpdyFramerTest, CatchProbableHttpResponse) { } TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyDataIR data_ir(1, "hello"); + scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); + EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~DATA_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, DataFrameFlagsV2V3disabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4425,6 +4474,60 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV2V3) { } TEST_P(SpdyFramerTest, DataFrameFlagsV4) { + FLAGS_spdy_on_stream_end = true; + + if (!IsHttp2()) { + return; + } + + uint8_t valid_data_flags = + DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED; + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyDataIR data_ir(1, "hello"); + scoped_ptr<SpdyFrame> frame(framer.SerializeData(data_ir)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~valid_data_flags) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN)); + if (flags & DATA_FLAG_PADDED) { + // The first byte of payload is parsed as padding length. + EXPECT_CALL(visitor, OnStreamPadding(_, 1)); + // Expect Error since the frame ends prematurely. + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5, false)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if ((flags & ~valid_data_flags) || (flags & DATA_FLAG_PADDED)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_DATA_FRAME_FLAGS, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, DataFrameFlagsV4disabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsHttp2()) { return; } @@ -4475,6 +4578,64 @@ TEST_P(SpdyFramerTest, DataFrameFlagsV4) { } TEST_P(SpdyFramerTest, SynStreamFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + testing::StrictMock<test::MockDebugVisitor> debug_visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + framer.set_debug_visitor(&debug_visitor); + + EXPECT_CALL(debug_visitor, OnSendCompressedFrame(8, SYN_STREAM, _, _)); + + SpdySynStreamIR syn_stream(8); + syn_stream.set_associated_to_stream_id(3); + syn_stream.set_priority(1); + syn_stream.SetHeader("foo", "bar"); + scoped_ptr<SpdyFrame> frame(framer.SerializeSynStream(syn_stream)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(8, SYN_STREAM, _)); + EXPECT_CALL(visitor, OnSynStream(8, 3, 1, flags & CONTROL_FLAG_FIN, + flags & CONTROL_FLAG_UNIDIRECTIONAL)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(8, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } else { + // Do not close the stream if we are expecting a CONTINUATION frame. + EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, SynStreamFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4529,6 +4690,53 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) { } TEST_P(SpdyFramerTest, SynReplyFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + if (!IsSpdy3()) { + return; + } + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdySynReplyIR syn_reply(37); + syn_reply.SetHeader("foo", "bar"); + scoped_ptr<SpdyFrame> frame(framer.SerializeSynReply(syn_reply)); + SetFrameFlags(frame.get(), flags, spdy_version_); + + if (flags & ~CONTROL_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else { + EXPECT_CALL(visitor, OnSynReply(37, flags & CONTROL_FLAG_FIN)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(37, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (flags & ~CONTROL_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, SynReplyFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + if (!IsSpdy3()) { return; } @@ -4729,6 +4937,99 @@ TEST_P(SpdyFramerTest, GoawayFrameFlags) { } TEST_P(SpdyFramerTest, HeadersFrameFlags) { + FLAGS_spdy_on_stream_end = true; + + uint8_t flags = 0; + do { + SCOPED_TRACE(testing::Message() << "Flags " << flags); + + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + SpdyFramer framer(spdy_version_); + framer.set_visitor(&visitor); + + SpdyHeadersIR headers_ir(57); + if (IsHttp2() && (flags & HEADERS_FLAG_PRIORITY)) { + headers_ir.set_priority(3); + headers_ir.set_has_priority(true); + headers_ir.set_parent_stream_id(5); + headers_ir.set_exclusive(true); + } + headers_ir.SetHeader("foo", "bar"); + std::unique_ptr<SpdyFrame> frame(framer.SerializeHeaders(headers_ir)); + uint8_t set_flags = flags; + if (IsHttp2()) { + // TODO(jgraettinger): Add padding to SpdyHeadersIR, + // and implement framing. + set_flags &= ~HEADERS_FLAG_PADDED; + } + SetFrameFlags(frame.get(), set_flags, spdy_version_); + + if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) { + EXPECT_CALL(visitor, OnError(_)); + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { + EXPECT_CALL(visitor, OnError(_)); + } else { + // Expected callback values + SpdyStreamId stream_id = 57; + bool has_priority = false; + SpdyPriority priority = 0; + SpdyStreamId parent_stream_id = 0; + bool exclusive = false; + bool fin = flags & CONTROL_FLAG_FIN; + bool end = IsSpdy3() || (flags & HEADERS_FLAG_END_HEADERS); + if (IsHttp2() && flags & HEADERS_FLAG_PRIORITY) { + has_priority = true; + priority = 3; + parent_stream_id = 5; + exclusive = true; + } + EXPECT_CALL(visitor, OnHeaders(stream_id, has_priority, priority, + parent_stream_id, exclusive, fin, end)); + EXPECT_CALL(visitor, OnControlFrameHeaderData(57, _, _)) + .WillRepeatedly(testing::Return(true)); + if (flags & DATA_FLAG_FIN && + (IsSpdy3() || flags & HEADERS_FLAG_END_HEADERS)) { + EXPECT_CALL(visitor, OnStreamEnd(_)); + } else { + // Do not close the stream if we are expecting a CONTINUATION frame. + EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0); + } + } + + framer.ProcessInput(frame->data(), frame->size()); + if (IsSpdy3() && flags & ~CONTROL_FLAG_FIN) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { + EXPECT_EQ(SpdyFramer::SPDY_ERROR, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_INVALID_CONTROL_FRAME_FLAGS, + framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else if (IsHttp2() && ~(flags & HEADERS_FLAG_END_HEADERS)) { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } else { + EXPECT_EQ(SpdyFramer::SPDY_READY_FOR_FRAME, framer.state()); + EXPECT_EQ(SpdyFramer::SPDY_NO_ERROR, framer.error_code()) + << SpdyFramer::ErrorCodeToString(framer.error_code()); + } + } while (++flags != 0); +} + +TEST_P(SpdyFramerTest, HeadersFrameFlagsDisabled) { + FLAGS_spdy_on_stream_end = false; + uint8_t flags = 0; do { SCOPED_TRACE(testing::Message() << "Flags " << flags); @@ -4756,11 +5057,11 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) { if (!IsHttp2() && flags & ~CONTROL_FLAG_FIN) { EXPECT_CALL(visitor, OnError(_)); - } else if (IsHttp2() && flags & ~(CONTROL_FLAG_FIN | - HEADERS_FLAG_END_HEADERS | - HEADERS_FLAG_END_SEGMENT | - HEADERS_FLAG_PADDED | - HEADERS_FLAG_PRIORITY)) { + } else if (IsHttp2() && + flags & + ~(CONTROL_FLAG_FIN | HEADERS_FLAG_END_HEADERS | + HEADERS_FLAG_END_SEGMENT | HEADERS_FLAG_PADDED | + HEADERS_FLAG_PRIORITY)) { EXPECT_CALL(visitor, OnError(_)); } else { // Expected callback values |
