| Index: net/quic/quic_headers_stream_test.cc
|
| diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc
|
| deleted file mode 100644
|
| index 10bc5c864854f740d7e928cd9f6b06747bcd7529..0000000000000000000000000000000000000000
|
| --- a/net/quic/quic_headers_stream_test.cc
|
| +++ /dev/null
|
| @@ -1,977 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/quic/quic_headers_stream.h"
|
| -
|
| -#include <string>
|
| -
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "net/quic/quic_bug_tracker.h"
|
| -#include "net/quic/quic_utils.h"
|
| -#include "net/quic/spdy_utils.h"
|
| -#include "net/quic/test_tools/quic_connection_peer.h"
|
| -#include "net/quic/test_tools/quic_headers_stream_peer.h"
|
| -#include "net/quic/test_tools/quic_spdy_session_peer.h"
|
| -#include "net/quic/test_tools/quic_test_utils.h"
|
| -#include "net/quic/test_tools/reliable_quic_stream_peer.h"
|
| -#include "net/spdy/spdy_alt_svc_wire_format.h"
|
| -#include "net/spdy/spdy_flags.h"
|
| -#include "net/spdy/spdy_protocol.h"
|
| -#include "net/spdy/spdy_test_utils.h"
|
| -#include "net/test/gtest_util.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using base::StringPiece;
|
| -using std::ostream;
|
| -using std::string;
|
| -using std::vector;
|
| -using testing::ElementsAre;
|
| -using testing::_;
|
| -using testing::AtLeast;
|
| -using testing::HasSubstr;
|
| -using testing::InSequence;
|
| -using testing::Invoke;
|
| -using testing::Return;
|
| -using testing::StrictMock;
|
| -using testing::WithArgs;
|
| -using testing::_;
|
| -
|
| -// TODO(bnc): Merge these correctly.
|
| -bool FLAGS_use_http2_frame_decoder_adapter;
|
| -bool FLAGS_spdy_use_hpack_decoder2;
|
| -bool FLAGS_spdy_framer_use_new_methods2;
|
| -
|
| -namespace net {
|
| -namespace test {
|
| -
|
| -class MockHpackDebugVisitor : public QuicHeadersStream::HpackDebugVisitor {
|
| - public:
|
| - explicit MockHpackDebugVisitor() : HpackDebugVisitor() {}
|
| -
|
| - MOCK_METHOD1(OnUseEntry, void(QuicTime::Delta elapsed));
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(MockHpackDebugVisitor);
|
| -};
|
| -
|
| -namespace {
|
| -
|
| -// TODO(ckrasic): this workaround is due to absence of std::initializer_list
|
| -const bool kFins[] = {false, true};
|
| -
|
| -class MockVisitor : public SpdyFramerVisitorInterface {
|
| - public:
|
| - MOCK_METHOD1(OnError, void(SpdyFramer* framer));
|
| - MOCK_METHOD3(OnDataFrameHeader,
|
| - void(SpdyStreamId stream_id, size_t length, bool fin));
|
| - MOCK_METHOD3(OnStreamFrameData,
|
| - void(SpdyStreamId stream_id, const char* data, size_t len));
|
| - MOCK_METHOD1(OnStreamEnd, void(SpdyStreamId stream_id));
|
| - MOCK_METHOD2(OnStreamPadding, void(SpdyStreamId stream_id, size_t len));
|
| - MOCK_METHOD1(OnHeaderFrameStart,
|
| - SpdyHeadersHandlerInterface*(SpdyStreamId stream_id));
|
| - MOCK_METHOD2(OnHeaderFrameEnd, void(SpdyStreamId stream_id, bool end));
|
| - MOCK_METHOD3(OnControlFrameHeaderData,
|
| - bool(SpdyStreamId stream_id,
|
| - const char* header_data,
|
| - size_t len));
|
| - MOCK_METHOD5(OnSynStream,
|
| - void(SpdyStreamId stream_id,
|
| - SpdyStreamId associated_stream_id,
|
| - SpdyPriority priority,
|
| - bool fin,
|
| - bool unidirectional));
|
| - MOCK_METHOD2(OnSynReply, void(SpdyStreamId stream_id, bool fin));
|
| - MOCK_METHOD2(OnRstStream,
|
| - void(SpdyStreamId stream_id, SpdyRstStreamStatus status));
|
| - MOCK_METHOD1(OnSettings, void(bool clear_persisted));
|
| - MOCK_METHOD3(OnSetting,
|
| - void(SpdySettingsIds id, uint8_t flags, uint32_t value));
|
| - MOCK_METHOD0(OnSettingsAck, void());
|
| - MOCK_METHOD0(OnSettingsEnd, void());
|
| - MOCK_METHOD2(OnPing, void(SpdyPingId unique_id, bool is_ack));
|
| - MOCK_METHOD2(OnGoAway,
|
| - void(SpdyStreamId last_accepted_stream_id,
|
| - SpdyGoAwayStatus status));
|
| - MOCK_METHOD7(OnHeaders,
|
| - void(SpdyStreamId stream_id,
|
| - bool has_priority,
|
| - int weight,
|
| - SpdyStreamId parent_stream_id,
|
| - bool exclusive,
|
| - bool fin,
|
| - bool end));
|
| - MOCK_METHOD2(OnWindowUpdate,
|
| - void(SpdyStreamId stream_id, int delta_window_size));
|
| - MOCK_METHOD1(OnBlocked, void(SpdyStreamId stream_id));
|
| - MOCK_METHOD3(OnPushPromise,
|
| - void(SpdyStreamId stream_id,
|
| - SpdyStreamId promised_stream_id,
|
| - bool end));
|
| - MOCK_METHOD2(OnContinuation, void(SpdyStreamId stream_id, bool end));
|
| - MOCK_METHOD4(OnPriority,
|
| - void(SpdyStreamId stream_id,
|
| - SpdyStreamId parent_id,
|
| - int weight,
|
| - bool exclusive));
|
| - MOCK_METHOD3(OnAltSvc,
|
| - void(SpdyStreamId stream_id,
|
| - StringPiece origin,
|
| - const SpdyAltSvcWireFormat::AlternativeServiceVector&
|
| - altsvc_vector));
|
| - MOCK_METHOD2(OnUnknownFrame, bool(SpdyStreamId stream_id, int frame_type));
|
| -};
|
| -
|
| -class ForceHolAckListener : public QuicAckListenerInterface {
|
| - public:
|
| - ForceHolAckListener() : total_acked_bytes_(0) {}
|
| -
|
| - void OnPacketAcked(int acked_bytes, QuicTime::Delta ack_delay_time) override {
|
| - total_acked_bytes_ += acked_bytes;
|
| - }
|
| -
|
| - void OnPacketRetransmitted(int retransmitted_bytes) override {}
|
| -
|
| - size_t total_acked_bytes() { return total_acked_bytes_; }
|
| -
|
| - private:
|
| - ~ForceHolAckListener() override {}
|
| -
|
| - size_t total_acked_bytes_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ForceHolAckListener);
|
| -};
|
| -
|
| -enum Http2DecoderChoice {
|
| - HTTP2_DECODER_SPDY,
|
| - HTTP2_DECODER_NESTED_SPDY,
|
| - HTTP2_DECODER_NEW
|
| -};
|
| -ostream& operator<<(ostream& os, Http2DecoderChoice v) {
|
| - switch (v) {
|
| - case HTTP2_DECODER_SPDY:
|
| - return os << "SPDY";
|
| - case HTTP2_DECODER_NESTED_SPDY:
|
| - return os << "NESTED_SPDY";
|
| - case HTTP2_DECODER_NEW:
|
| - return os << "NEW";
|
| - }
|
| - return os;
|
| -}
|
| -
|
| -enum HpackDecoderChoice { HPACK_DECODER_SPDY, HPACK_DECODER_NEW };
|
| -ostream& operator<<(ostream& os, HpackDecoderChoice v) {
|
| - switch (v) {
|
| - case HPACK_DECODER_SPDY:
|
| - return os << "SPDY";
|
| - case HPACK_DECODER_NEW:
|
| - return os << "NEW";
|
| - }
|
| - return os;
|
| -}
|
| -
|
| -typedef std::
|
| - tuple<QuicVersion, Perspective, Http2DecoderChoice, HpackDecoderChoice>
|
| - TestParamsTuple;
|
| -
|
| -struct TestParams {
|
| - explicit TestParams(TestParamsTuple params)
|
| - : version(std::get<0>(params)),
|
| - perspective(std::get<1>(params)),
|
| - http2_decoder(std::get<2>(params)),
|
| - hpack_decoder(std::get<3>(params)) {
|
| - switch (http2_decoder) {
|
| - case HTTP2_DECODER_SPDY:
|
| - FLAGS_use_nested_spdy_framer_decoder = false;
|
| - FLAGS_use_http2_frame_decoder_adapter = false;
|
| - break;
|
| - case HTTP2_DECODER_NESTED_SPDY:
|
| - FLAGS_use_nested_spdy_framer_decoder = true;
|
| - FLAGS_use_http2_frame_decoder_adapter = false;
|
| - break;
|
| - case HTTP2_DECODER_NEW:
|
| - FLAGS_use_nested_spdy_framer_decoder = false;
|
| - FLAGS_use_http2_frame_decoder_adapter = true;
|
| - // Http2FrameDecoderAdapter needs the new header methods, else
|
| - // --use_http2_frame_decoder_adapter=true will be ignored.
|
| - FLAGS_spdy_framer_use_new_methods2 = true;
|
| - break;
|
| - }
|
| - switch (hpack_decoder) {
|
| - case HPACK_DECODER_SPDY:
|
| - FLAGS_spdy_use_hpack_decoder2 = false;
|
| - break;
|
| - case HPACK_DECODER_NEW:
|
| - FLAGS_spdy_use_hpack_decoder2 = true;
|
| - // Needs new header methods to be used.
|
| - FLAGS_spdy_framer_use_new_methods2 = true;
|
| - break;
|
| - }
|
| - FLAGS_quic_supports_push_promise = true;
|
| - FLAGS_quic_always_log_bugs_for_tests = true;
|
| - VLOG(1) << "TestParams: version: " << QuicVersionToString(version)
|
| - << ", perspective: " << perspective
|
| - << ", http2_decoder: " << http2_decoder
|
| - << ", hpack_decoder: " << hpack_decoder;
|
| - }
|
| -
|
| - QuicVersion version;
|
| - Perspective perspective;
|
| - Http2DecoderChoice http2_decoder;
|
| - HpackDecoderChoice hpack_decoder;
|
| -};
|
| -
|
| -class QuicHeadersStreamTest : public ::testing::TestWithParam<TestParamsTuple> {
|
| - public:
|
| - // Constructing the test_params_ object will set the necessary flags before
|
| - // the MockQuicConnection is constructed, which we need because the latter
|
| - // will construct a SpdyFramer that will use those flags to decide whether
|
| - // to construct a decoder adapter.
|
| - QuicHeadersStreamTest()
|
| - : test_params_(GetParam()),
|
| - connection_(new StrictMock<MockQuicConnection>(&helper_,
|
| - &alarm_factory_,
|
| - perspective(),
|
| - GetVersion())),
|
| - session_(connection_),
|
| - headers_stream_(QuicSpdySessionPeer::GetHeadersStream(&session_)),
|
| - body_("hello world"),
|
| - hpack_encoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
|
| - hpack_decoder_visitor_(new StrictMock<MockHpackDebugVisitor>),
|
| - stream_frame_(kHeadersStreamId, /*fin=*/false, /*offset=*/0, ""),
|
| - next_promised_stream_id_(2) {
|
| - headers_[":version"] = "HTTP/1.1";
|
| - headers_[":status"] = "200 Ok";
|
| - headers_["content-length"] = "11";
|
| - framer_ = std::unique_ptr<SpdyFramer>(new SpdyFramer(HTTP2));
|
| - framer_->set_visitor(&visitor_);
|
| - EXPECT_EQ(version(), session_.connection()->version());
|
| - EXPECT_TRUE(headers_stream_ != nullptr);
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - }
|
| -
|
| - QuicConsumedData SaveIov(const QuicIOVector& data) {
|
| - const iovec* iov = data.iov;
|
| - int count = data.iov_count;
|
| - int consumed = 0;
|
| - for (int i = 0; i < count; ++i) {
|
| - saved_data_.append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
|
| - consumed += iov[i].iov_len;
|
| - }
|
| - return QuicConsumedData(consumed, false);
|
| - }
|
| -
|
| - QuicConsumedData SaveIovAndNotifyAckListener(
|
| - const QuicIOVector& data,
|
| - QuicAckListenerInterface* ack_listener) {
|
| - QuicConsumedData result = SaveIov(data);
|
| - if (ack_listener) {
|
| - ack_listener->OnPacketAcked(result.bytes_consumed,
|
| - QuicTime::Delta::Zero());
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - void SavePayload(const char* data, size_t len) {
|
| - saved_payloads_.append(data, len);
|
| - }
|
| -
|
| - bool SaveHeaderData(const char* data, int len) {
|
| - saved_header_data_.append(data, len);
|
| - return true;
|
| - }
|
| -
|
| - void SaveHeaderDataStringPiece(StringPiece data) {
|
| - saved_header_data_.append(data.data(), data.length());
|
| - }
|
| -
|
| - void SavePromiseHeaderList(QuicStreamId /* stream_id */,
|
| - QuicStreamId /* promised_stream_id */,
|
| - size_t size,
|
| - const QuicHeaderList& header_list) {
|
| - SaveToHandler(size, header_list);
|
| - }
|
| -
|
| - void SaveHeaderList(QuicStreamId /* stream_id */,
|
| - bool /* fin */,
|
| - size_t size,
|
| - const QuicHeaderList& header_list) {
|
| - SaveToHandler(size, header_list);
|
| - }
|
| -
|
| - void SaveToHandler(size_t size, const QuicHeaderList& header_list) {
|
| - headers_handler_.reset(new TestHeadersHandler);
|
| - headers_handler_->OnHeaderBlockStart();
|
| - for (const auto& p : header_list) {
|
| - headers_handler_->OnHeader(p.first, p.second);
|
| - }
|
| - headers_handler_->OnHeaderBlockEnd(size);
|
| - }
|
| -
|
| - void WriteHeadersAndExpectSynStream(QuicStreamId stream_id,
|
| - bool fin,
|
| - SpdyPriority priority) {
|
| - WriteHeadersAndCheckData(stream_id, fin, priority, SYN_STREAM);
|
| - }
|
| -
|
| - void WriteHeadersAndExpectSynReply(QuicStreamId stream_id, bool fin) {
|
| - WriteHeadersAndCheckData(stream_id, fin, 0, SYN_REPLY);
|
| - }
|
| -
|
| - void WriteHeadersAndCheckData(QuicStreamId stream_id,
|
| - bool fin,
|
| - SpdyPriority priority,
|
| - SpdyFrameType type) {
|
| - // Write the headers and capture the outgoing data
|
| - EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
|
| - false, nullptr))
|
| - .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
|
| - headers_stream_->WriteHeaders(stream_id, headers_.Clone(), fin, priority,
|
| - nullptr);
|
| -
|
| - // Parse the outgoing data and check that it matches was was written.
|
| - if (type == SYN_STREAM) {
|
| - EXPECT_CALL(visitor_,
|
| - OnHeaders(stream_id, kHasPriority,
|
| - Spdy3PriorityToHttp2Weight(priority),
|
| - /*parent_stream_id=*/0,
|
| - /*exclusive=*/false, fin, kFrameComplete));
|
| - } else {
|
| - EXPECT_CALL(visitor_,
|
| - OnHeaders(stream_id, !kHasPriority,
|
| - /*priority=*/0,
|
| - /*parent_stream_id=*/0,
|
| - /*exclusive=*/false, fin, kFrameComplete));
|
| - }
|
| - headers_handler_.reset(new TestHeadersHandler);
|
| - EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
|
| - .WillOnce(Return(headers_handler_.get()));
|
| - EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id, true)).Times(1);
|
| - if (fin) {
|
| - EXPECT_CALL(visitor_, OnStreamEnd(stream_id));
|
| - }
|
| - framer_->ProcessInput(saved_data_.data(), saved_data_.length());
|
| - EXPECT_FALSE(framer_->HasError())
|
| - << SpdyFramer::ErrorCodeToString(framer_->error_code());
|
| -
|
| - CheckHeaders();
|
| - saved_data_.clear();
|
| - }
|
| -
|
| - void CheckHeaders() {
|
| - EXPECT_EQ(headers_, headers_handler_->decoded_block());
|
| - headers_handler_.reset();
|
| - }
|
| -
|
| - Perspective perspective() const { return test_params_.perspective; }
|
| -
|
| - QuicVersion version() const { return test_params_.version; }
|
| -
|
| - QuicVersionVector GetVersion() {
|
| - QuicVersionVector versions;
|
| - versions.push_back(version());
|
| - return versions;
|
| - }
|
| -
|
| - void TearDownLocalConnectionState() {
|
| - QuicConnectionPeer::TearDownLocalConnectionState(connection_);
|
| - }
|
| -
|
| - QuicStreamId NextPromisedStreamId() { return next_promised_stream_id_ += 2; }
|
| -
|
| - static const bool kFrameComplete = true;
|
| - static const bool kHasPriority = true;
|
| -
|
| - const TestParams test_params_;
|
| - MockQuicConnectionHelper helper_;
|
| - MockAlarmFactory alarm_factory_;
|
| - StrictMock<MockQuicConnection>* connection_;
|
| - StrictMock<MockQuicSpdySession> session_;
|
| - QuicHeadersStream* headers_stream_;
|
| - SpdyHeaderBlock headers_;
|
| - std::unique_ptr<TestHeadersHandler> headers_handler_;
|
| - string body_;
|
| - string saved_data_;
|
| - string saved_header_data_;
|
| - string saved_payloads_;
|
| - std::unique_ptr<SpdyFramer> framer_;
|
| - StrictMock<MockVisitor> visitor_;
|
| - std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_encoder_visitor_;
|
| - std::unique_ptr<StrictMock<MockHpackDebugVisitor>> hpack_decoder_visitor_;
|
| - QuicStreamFrame stream_frame_;
|
| - QuicStreamId next_promised_stream_id_;
|
| -};
|
| -
|
| -// Run all tests with each version, perspective (client or server),
|
| -// HTTP/2 and HPACK decoder.
|
| -INSTANTIATE_TEST_CASE_P(
|
| - Tests,
|
| - QuicHeadersStreamTest,
|
| - ::testing::Combine(
|
| - ::testing::ValuesIn(QuicSupportedVersions()),
|
| - ::testing::Values(Perspective::IS_CLIENT, Perspective::IS_SERVER),
|
| - ::testing::Values(HTTP2_DECODER_SPDY,
|
| - HTTP2_DECODER_NESTED_SPDY,
|
| - HTTP2_DECODER_NEW),
|
| - ::testing::Values(HPACK_DECODER_SPDY, HPACK_DECODER_NEW)));
|
| -
|
| -TEST_P(QuicHeadersStreamTest, StreamId) {
|
| - EXPECT_EQ(3u, headers_stream_->id());
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, WriteHeaders) {
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - for (bool fin : kFins) {
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - WriteHeadersAndExpectSynReply(stream_id, fin);
|
| - } else {
|
| - for (SpdyPriority priority = 0; priority < 7; ++priority) {
|
| - // TODO(rch): implement priorities correctly.
|
| - WriteHeadersAndExpectSynStream(stream_id, fin, 0);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, WritePushPromises) {
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - QuicStreamId promised_stream_id = NextPromisedStreamId();
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - // Write the headers and capture the outgoing data
|
| - EXPECT_CALL(session_, WritevData(headers_stream_, kHeadersStreamId, _, _,
|
| - false, nullptr))
|
| - .WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
|
| - headers_stream_->WritePushPromise(stream_id, promised_stream_id,
|
| - headers_.Clone(), nullptr);
|
| -
|
| - // Parse the outgoing data and check that it matches was was written.
|
| - EXPECT_CALL(visitor_,
|
| - OnPushPromise(stream_id, promised_stream_id, kFrameComplete));
|
| - headers_handler_.reset(new TestHeadersHandler);
|
| - EXPECT_CALL(visitor_, OnHeaderFrameStart(stream_id))
|
| - .WillOnce(Return(headers_handler_.get()));
|
| - EXPECT_CALL(visitor_, OnHeaderFrameEnd(stream_id, true)).Times(1);
|
| - framer_->ProcessInput(saved_data_.data(), saved_data_.length());
|
| - EXPECT_FALSE(framer_->HasError())
|
| - << SpdyFramer::ErrorCodeToString(framer_->error_code());
|
| - CheckHeaders();
|
| - saved_data_.clear();
|
| - } else {
|
| - EXPECT_DFATAL(
|
| - headers_stream_->WritePushPromise(stream_id, promised_stream_id,
|
| - headers_.Clone(), nullptr),
|
| - "Client shouldn't send PUSH_PROMISE");
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessRawData) {
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - for (bool fin : {false, true}) {
|
| - for (SpdyPriority priority = 0; priority < 7; ++priority) {
|
| - // Replace with "WriteHeadersAndSaveData"
|
| - SpdySerializedFrame frame;
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - headers_frame.set_has_priority(true);
|
| - headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
|
| - } else {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - }
|
| - EXPECT_CALL(session_,
|
| - OnStreamHeaderList(stream_id, fin, frame.size(), _))
|
| - .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - stream_frame_.offset += frame.size();
|
| - CheckHeaders();
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessPushPromise) {
|
| - if (perspective() == Perspective::IS_SERVER)
|
| - return;
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - QuicStreamId promised_stream_id = NextPromisedStreamId();
|
| - SpdyPushPromiseIR push_promise(stream_id, promised_stream_id,
|
| - headers_.Clone());
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(push_promise));
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "PUSH_PROMISE not supported.", _))
|
| - .WillRepeatedly(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - } else {
|
| - EXPECT_CALL(session_, OnPromiseHeaderList(stream_id, promised_stream_id,
|
| - frame.size(), _))
|
| - .WillOnce(
|
| - Invoke(this, &QuicHeadersStreamTest::SavePromiseHeaderList));
|
| - }
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - if (perspective() == Perspective::IS_CLIENT) {
|
| - stream_frame_.offset += frame.size();
|
| - CheckHeaders();
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) {
|
| - if (!FLAGS_quic_measure_headers_hol_blocking_time) {
|
| - return;
|
| - }
|
| - EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(0);
|
| - testing::InSequence seq;
|
| - bool fin = true;
|
| - for (int stream_num = 0; stream_num < 10; stream_num++) {
|
| - QuicStreamId stream_id = QuicClientDataStreamId(stream_num);
|
| - // Replace with "WriteHeadersAndSaveData"
|
| - SpdySerializedFrame frame;
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - headers_frame.set_has_priority(true);
|
| - headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
|
| - } else {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - }
|
| - EXPECT_CALL(session_, OnStreamHeaderList(stream_id, fin, frame.size(), _))
|
| - .Times(1);
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - stream_frame_.offset += frame.size();
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) {
|
| - QuicStreamId stream_id;
|
| - bool fin = true;
|
| - QuicStreamFrame stream_frames[10];
|
| - SpdySerializedFrame frames[10];
|
| - // First create all the frames in order
|
| - {
|
| - InSequence seq;
|
| - for (int stream_num = 0; stream_num < 10; ++stream_num) {
|
| - stream_id = QuicClientDataStreamId(stream_num);
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - headers_frame.set_has_priority(true);
|
| - headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
|
| - frames[stream_num] = framer_->SerializeFrame(headers_frame);
|
| - EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0)).Times(1);
|
| - } else {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - frames[stream_num] = framer_->SerializeFrame(headers_frame);
|
| - }
|
| - stream_frames[stream_num].stream_id = stream_frame_.stream_id;
|
| - stream_frames[stream_num].offset = stream_frame_.offset;
|
| - stream_frames[stream_num].data_buffer = frames[stream_num].data();
|
| - stream_frames[stream_num].data_length = frames[stream_num].size();
|
| - DVLOG(1) << "make frame for stream " << stream_num << " offset "
|
| - << stream_frames[stream_num].offset;
|
| - stream_frame_.offset += frames[stream_num].size();
|
| - EXPECT_CALL(session_, OnStreamHeaderList(stream_id, fin, _, _)).Times(1);
|
| - }
|
| - }
|
| -
|
| - // Actually writing the frames in reverse order will cause HOL blocking.
|
| - EXPECT_CALL(session_, OnHeadersHeadOfLineBlocking(_)).Times(9);
|
| -
|
| - for (int stream_num = 9; stream_num >= 0; --stream_num) {
|
| - DVLOG(1) << "OnStreamFrame for stream " << stream_num << " offset "
|
| - << stream_frames[stream_num].offset;
|
| - headers_stream_->OnStreamFrame(stream_frames[stream_num]);
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) {
|
| - // We want to create a frame that is more than the SPDY Framer's max control
|
| - // frame size, which is 16K, but less than the HPACK decoders max decode
|
| - // buffer size, which is 32K.
|
| - headers_["key0"] = string(1 << 13, '.');
|
| - headers_["key1"] = string(1 << 13, '.');
|
| - headers_["key2"] = string(1 << 13, '.');
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - for (bool fin : {false, true}) {
|
| - for (SpdyPriority priority = 0; priority < 7; ++priority) {
|
| - // Replace with "WriteHeadersAndSaveData"
|
| - SpdySerializedFrame frame;
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - headers_frame.set_has_priority(true);
|
| - headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
|
| - } else {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - }
|
| - EXPECT_CALL(session_,
|
| - OnStreamHeaderList(stream_id, fin, frame.size(), _))
|
| - .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - stream_frame_.offset += frame.size();
|
| - CheckHeaders();
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessBadData) {
|
| - const char kBadData[] = "blah blah blah";
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA, _, _))
|
| - .Times(::testing::AnyNumber());
|
| - stream_frame_.data_buffer = kBadData;
|
| - stream_frame_.data_length = strlen(kBadData);
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) {
|
| - SpdyDataIR data(2, "ping");
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| -
|
| - EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY DATA frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameForceHolBlocking) {
|
| - if (version() <= QUIC_VERSION_35) {
|
| - return;
|
| - }
|
| - QuicSpdySessionPeer::SetForceHolBlocking(&session_, true);
|
| - SpdyDataIR data(2, "ping");
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(session_, OnStreamFrameData(2, _, 4, false));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrameEmptyWithFin) {
|
| - if (version() <= QUIC_VERSION_35) {
|
| - return;
|
| - }
|
| - QuicSpdySessionPeer::SetForceHolBlocking(&session_, true);
|
| - SpdyDataIR data(2, "");
|
| - data.set_fin(true);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(session_, OnStreamFrameData(2, _, 0, true));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) {
|
| - SpdyRstStreamIR data(2, RST_STREAM_PROTOCOL_ERROR);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY RST_STREAM frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) {
|
| - FLAGS_quic_respect_http2_settings_frame = false;
|
| - SpdySettingsIR data;
|
| - data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, 0);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY SETTINGS frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameSupportedFields) {
|
| - FLAGS_quic_respect_http2_settings_frame = true;
|
| - const uint32_t kTestHeaderTableSize = 1000;
|
| - SpdySettingsIR data;
|
| - // Respect supported settings frames SETTINGS_HEADER_TABLE_SIZE.
|
| - data.AddSetting(SETTINGS_HEADER_TABLE_SIZE, true, true, kTestHeaderTableSize);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - EXPECT_EQ(kTestHeaderTableSize,
|
| - QuicHeadersStreamPeer::GetSpdyFramer(headers_stream_)
|
| - .header_encoder_table_size());
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, RespectHttp2SettingsFrameUnsupportedFields) {
|
| - FLAGS_quic_respect_http2_settings_frame = true;
|
| - SpdySettingsIR data;
|
| - // Does not support SETTINGS_MAX_HEADER_LIST_SIZE,
|
| - // SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
|
| - // SETTINGS_ENABLE_PUSH and SETTINGS_MAX_FRAME_SIZE.
|
| - data.AddSetting(SETTINGS_MAX_HEADER_LIST_SIZE, true, true, 2000);
|
| - data.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, true, true, 100);
|
| - data.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, true, true, 100);
|
| - data.AddSetting(SETTINGS_ENABLE_PUSH, true, true, 1);
|
| - data.AddSetting(SETTINGS_MAX_FRAME_SIZE, true, true, 1250);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(
|
| - *connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "Unsupported field of HTTP/2 SETTINGS frame: " +
|
| - base::IntToString(SETTINGS_MAX_HEADER_LIST_SIZE),
|
| - _));
|
| - EXPECT_CALL(
|
| - *connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "Unsupported field of HTTP/2 SETTINGS frame: " +
|
| - base::IntToString(SETTINGS_MAX_CONCURRENT_STREAMS),
|
| - _));
|
| - EXPECT_CALL(
|
| - *connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "Unsupported field of HTTP/2 SETTINGS frame: " +
|
| - base::IntToString(SETTINGS_INITIAL_WINDOW_SIZE),
|
| - _));
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "Unsupported field of HTTP/2 SETTINGS frame: " +
|
| - base::IntToString(SETTINGS_ENABLE_PUSH),
|
| - _));
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "Unsupported field of HTTP/2 SETTINGS frame: " +
|
| - base::IntToString(SETTINGS_MAX_FRAME_SIZE),
|
| - _));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) {
|
| - SpdyPingIR data(1);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY PING frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) {
|
| - SpdyGoAwayIR data(1, GOAWAY_PROTOCOL_ERROR, "go away");
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY GOAWAY frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) {
|
| - SpdyWindowUpdateIR data(1, 1);
|
| - SpdySerializedFrame frame(framer_->SerializeFrame(data));
|
| - EXPECT_CALL(*connection_,
|
| - CloseConnection(QUIC_INVALID_HEADERS_STREAM_DATA,
|
| - "SPDY WINDOW_UPDATE frame received.", _))
|
| - .WillOnce(InvokeWithoutArgs(
|
| - this, &QuicHeadersStreamTest::TearDownLocalConnectionState));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, NoConnectionLevelFlowControl) {
|
| - EXPECT_FALSE(ReliableQuicStreamPeer::StreamContributesToConnectionFlowControl(
|
| - headers_stream_));
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, HpackDecoderDebugVisitor) {
|
| - if (FLAGS_use_nested_spdy_framer_decoder)
|
| - return;
|
| -
|
| - StrictMock<MockHpackDebugVisitor>* hpack_decoder_visitor =
|
| - hpack_decoder_visitor_.get();
|
| - headers_stream_->SetHpackDecoderDebugVisitor(
|
| - std::move(hpack_decoder_visitor_));
|
| -
|
| - // Create some headers we expect to generate entries in HPACK's
|
| - // dynamic table, in addition to content-length.
|
| - headers_["key0"] = string(1 << 1, '.');
|
| - headers_["key1"] = string(1 << 2, '.');
|
| - headers_["key2"] = string(1 << 3, '.');
|
| - {
|
| - testing::InSequence seq;
|
| - // Number of indexed representations generated in headers below.
|
| - for (int i = 1; i < 28; i++) {
|
| - EXPECT_CALL(*hpack_decoder_visitor,
|
| - OnUseEntry(QuicTime::Delta::FromMilliseconds(i)))
|
| - .Times(4);
|
| - }
|
| - }
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - for (bool fin : {false, true}) {
|
| - for (SpdyPriority priority = 0; priority < 7; ++priority) {
|
| - // Replace with "WriteHeadersAndSaveData"
|
| - SpdySerializedFrame frame;
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - headers_frame.set_has_priority(true);
|
| - headers_frame.set_weight(Spdy3PriorityToHttp2Weight(0));
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - EXPECT_CALL(session_, OnStreamHeadersPriority(stream_id, 0));
|
| - } else {
|
| - SpdyHeadersIR headers_frame(stream_id, headers_.Clone());
|
| - headers_frame.set_fin(fin);
|
| - frame = framer_->SerializeFrame(headers_frame);
|
| - }
|
| - EXPECT_CALL(session_,
|
| - OnStreamHeaderList(stream_id, fin, frame.size(), _))
|
| - .WillOnce(Invoke(this, &QuicHeadersStreamTest::SaveHeaderList));
|
| - stream_frame_.data_buffer = frame.data();
|
| - stream_frame_.data_length = frame.size();
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - headers_stream_->OnStreamFrame(stream_frame_);
|
| - stream_frame_.offset += frame.size();
|
| - CheckHeaders();
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, HpackEncoderDebugVisitor) {
|
| - StrictMock<MockHpackDebugVisitor>* hpack_encoder_visitor =
|
| - hpack_encoder_visitor_.get();
|
| - headers_stream_->SetHpackEncoderDebugVisitor(
|
| - std::move(hpack_encoder_visitor_));
|
| -
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - testing::InSequence seq;
|
| - for (int i = 1; i < 4; i++) {
|
| - EXPECT_CALL(*hpack_encoder_visitor,
|
| - OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
|
| - }
|
| - } else {
|
| - testing::InSequence seq;
|
| - for (int i = 1; i < 28; i++) {
|
| - EXPECT_CALL(*hpack_encoder_visitor,
|
| - OnUseEntry(QuicTime::Delta::FromMilliseconds(i)));
|
| - }
|
| - }
|
| - for (QuicStreamId stream_id = kClientDataStreamId1;
|
| - stream_id < kClientDataStreamId3; stream_id += 2) {
|
| - for (bool fin : {false, true}) {
|
| - if (perspective() == Perspective::IS_SERVER) {
|
| - WriteHeadersAndExpectSynReply(stream_id, fin);
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - } else {
|
| - for (SpdyPriority priority = 0; priority < 7; ++priority) {
|
| - // TODO(rch): implement priorities correctly.
|
| - WriteHeadersAndExpectSynStream(stream_id, fin, 0);
|
| - connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -TEST_P(QuicHeadersStreamTest, WritevStreamData) {
|
| - QuicStreamId id = kClientDataStreamId1;
|
| - QuicStreamOffset offset = 0;
|
| - struct iovec iov;
|
| - string data;
|
| -
|
| - // This test will issue a write that will require fragmenting into
|
| - // multiple HTTP/2 DATA frames.
|
| - const int kMinDataFrames = 4;
|
| - const size_t data_len =
|
| - kSpdyInitialFrameSizeLimit * kMinDataFrames + 1024;
|
| - // Set headers stream send window large enough for data written below.
|
| - headers_stream_->flow_controller()->UpdateSendWindowOffset(data_len * 2 * 4);
|
| - test::GenerateBody(&data, data_len);
|
| -
|
| - for (bool fin : {true, false}) {
|
| - for (bool use_ack_listener : {true, false}) {
|
| - scoped_refptr<ForceHolAckListener> ack_listener;
|
| - if (use_ack_listener) {
|
| - ack_listener = new ForceHolAckListener();
|
| - }
|
| - EXPECT_CALL(session_,
|
| - WritevData(headers_stream_, kHeadersStreamId, _, _, false, _))
|
| - .WillRepeatedly(WithArgs<2, 5>(Invoke(
|
| - this, &QuicHeadersStreamTest::SaveIovAndNotifyAckListener)));
|
| -
|
| - QuicConsumedData consumed_data = headers_stream_->WritevStreamData(
|
| - id, MakeIOVector(data, &iov), offset, fin, ack_listener.get());
|
| -
|
| - EXPECT_EQ(consumed_data.bytes_consumed, data_len);
|
| - EXPECT_EQ(consumed_data.fin_consumed, fin);
|
| - // Now process the written data with the SPDY framer, and verify
|
| - // that the original data is unchanged.
|
| - EXPECT_CALL(visitor_, OnDataFrameHeader(id, _, _))
|
| - .Times(AtLeast(kMinDataFrames));
|
| - EXPECT_CALL(visitor_, OnStreamFrameData(id, _, _))
|
| - .WillRepeatedly(WithArgs<1, 2>(
|
| - Invoke(this, &QuicHeadersStreamTest::SavePayload)));
|
| - if (fin) {
|
| - EXPECT_CALL(visitor_, OnStreamEnd(id));
|
| - }
|
| - framer_->ProcessInput(saved_data_.data(), saved_data_.length());
|
| - EXPECT_EQ(saved_payloads_, data);
|
| -
|
| - if (use_ack_listener) {
|
| - // Notice, acked bytes doesn't include extra bytes used by
|
| - // HTTP/2 DATA frame headers.
|
| - EXPECT_EQ(ack_listener->total_acked_bytes(), data_len);
|
| - }
|
| - saved_data_.clear();
|
| - saved_payloads_.clear();
|
| - }
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -} // namespace test
|
| -} // namespace net
|
|
|