Include encoder stream bytes in written header size. Include the total size of dynamic table insertion instructions (including duplications) sent on the encoder stream triggered by encoding a header list in the return value of QuicSpdyStream::WriteHeadersImpl(). gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99. PiperOrigin-RevId: 268203243 Change-Id: I5aacf67592862747670192a598c0aa877cb0c658
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc index a59100a..9e94a10 100644 --- a/quic/core/http/end_to_end_test.cc +++ b/quic/core/http/end_to_end_test.cc
@@ -2475,7 +2475,7 @@ qpack_encoder.set_qpack_stream_sender_delegate( &encoder_stream_sender_delegate); std::string encoded_headers = - qpack_encoder.EncodeHeaderList(/* stream_id = */ 0, headers); + qpack_encoder.EncodeHeaderList(/* stream_id = */ 0, headers, nullptr); header_size = encoded_headers.size(); }
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 2c32891..53ec3cc 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -555,7 +555,7 @@ // Encode header list. std::string encoded_headers = - qpack_encoder_->EncodeHeaderList(original_stream_id, headers); + qpack_encoder_->EncodeHeaderList(original_stream_id, headers, nullptr); PushPromiseFrame frame; frame.push_id = promised_stream_id; frame.headers = encoded_headers;
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 223442c..e702e85 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -1010,8 +1010,10 @@ } // Encode header list. + QuicByteCount encoder_stream_sent_byte_count; std::string encoded_headers = - spdy_session_->qpack_encoder()->EncodeHeaderList(id(), header_block); + spdy_session_->qpack_encoder()->EncodeHeaderList( + id(), header_block, &encoder_stream_sent_byte_count); // Write HEADERS frame. std::unique_ptr<char[]> headers_frame_header; @@ -1034,7 +1036,7 @@ << encoded_headers.length(); WriteOrBufferData(encoded_headers, fin, nullptr); - return encoded_headers.size(); + return encoded_headers.size() + encoder_stream_sent_byte_count; } void QuicSpdyStream::PopulatePriorityFrame(PriorityFrame* frame) {
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h index 42f76bb..4849705 100644 --- a/quic/core/http/quic_spdy_stream.h +++ b/quic/core/http/quic_spdy_stream.h
@@ -110,7 +110,9 @@ virtual void OnBodyAvailable() = 0; // Writes the headers contained in |header_block| on the dedicated headers - // stream or on this stream, depending on VersionUsesQpack(). + // stream or on this stream, depending on VersionUsesQpack(). Returns the + // number of bytes sent, including data sent on the encoder stream when using + // QPACK. virtual size_t WriteHeaders( spdy::SpdyHeaderBlock header_block, bool fin, @@ -121,7 +123,8 @@ // Writes the trailers contained in |trailer_block| on the dedicated headers // stream or on this stream, depending on VersionUsesQpack(). Trailers will - // always have the FIN flag set. + // always have the FIN flag set. Returns the number of bytes sent, including + // data sent on the encoder stream when using QPACK. virtual size_t WriteTrailers( spdy::SpdyHeaderBlock trailer_block, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc index 3fcf853..5e4dfcb 100644 --- a/quic/core/http/quic_spdy_stream_test.cc +++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -184,7 +184,8 @@ &encoder_stream_sender_delegate); // QpackEncoder does not use the dynamic table by default, // therefore the value of |stream_id| does not matter. - return qpack_encoder->EncodeHeaderList(/* stream_id = */ 0, header); + return qpack_encoder->EncodeHeaderList(/* stream_id = */ 0, header, + nullptr); } void Initialize(bool stream_should_process_data) {
diff --git a/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc index 8527483..996aa70 100644 --- a/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc +++ b/quic/core/qpack/fuzzer/qpack_round_trip_fuzzer.cc
@@ -55,7 +55,7 @@ std::string EncodeHeaderList(QuicStreamId stream_id, const spdy::SpdyHeaderBlock& header_list) { - return encoder_.EncodeHeaderList(stream_id, header_list); + return encoder_.EncodeHeaderList(stream_id, header_list, nullptr); } private:
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc index d1736f8..24f12bb 100644 --- a/quic/core/qpack/qpack_encoder.cc +++ b/quic/core/qpack/qpack_encoder.cc
@@ -87,9 +87,11 @@ QpackEncoder::Instructions QpackEncoder::FirstPassEncode( const spdy::SpdyHeaderBlock& header_list, - QpackBlockingManager::IndexSet* referred_indices) { + QpackBlockingManager::IndexSet* referred_indices, + QuicByteCount* encoder_stream_sent_byte_count) { Instructions instructions; instructions.reserve(header_list.size()); + QuicByteCount sent_byte_count = 0; // The index of the oldest entry that must not be evicted. uint64_t smallest_blocking_index = @@ -144,7 +146,7 @@ header_table_.MaxInsertSizeWithoutEvictingGivenEntry( std::min(smallest_blocking_index, index))) { // If allowed, duplicate entry and refer to it. - encoder_stream_sender_.SendDuplicate( + sent_byte_count += encoder_stream_sender_.SendDuplicate( QpackAbsoluteIndexToEncoderStreamRelativeIndex( index, header_table_.inserted_entry_count())); auto entry = header_table_.InsertEntry(name, value); @@ -174,8 +176,9 @@ header_table_.MaxInsertSizeWithoutEvictingGivenEntry( smallest_blocking_index)) { // If allowed, insert entry into dynamic table and refer to it. - encoder_stream_sender_.SendInsertWithNameReference(is_static, index, - value); + sent_byte_count += + encoder_stream_sender_.SendInsertWithNameReference( + is_static, index, value); auto entry = header_table_.InsertEntry(name, value); instructions.push_back(EncodeIndexedHeaderField( /* is_static = */ false, entry->InsertionIndex(), @@ -198,7 +201,7 @@ header_table_.MaxInsertSizeWithoutEvictingGivenEntry( std::min(smallest_blocking_index, index))) { // If allowed, insert entry with name reference and refer to it. - encoder_stream_sender_.SendInsertWithNameReference( + sent_byte_count += encoder_stream_sender_.SendInsertWithNameReference( is_static, QpackAbsoluteIndexToEncoderStreamRelativeIndex( index, header_table_.inserted_entry_count()), @@ -238,7 +241,9 @@ header_table_.MaxInsertSizeWithoutEvictingGivenEntry( smallest_blocking_index)) { // If allowed, insert entry and refer to it. - encoder_stream_sender_.SendInsertWithoutNameReference(name, value); + sent_byte_count += + encoder_stream_sender_.SendInsertWithoutNameReference(name, + value); auto entry = header_table_.InsertEntry(name, value); instructions.push_back(EncodeIndexedHeaderField( /* is_static = */ false, entry->InsertionIndex(), @@ -256,6 +261,12 @@ } } + // Use local |sent_byte_count| variable to avoid branching and dereferencing + // each time encoder stream data is sent. + if (encoder_stream_sent_byte_count) { + *encoder_stream_sent_byte_count = sent_byte_count; + } + return instructions; } @@ -296,13 +307,15 @@ std::string QpackEncoder::EncodeHeaderList( QuicStreamId stream_id, - const spdy::SpdyHeaderBlock& header_list) { + const spdy::SpdyHeaderBlock& header_list, + QuicByteCount* encoder_stream_sent_byte_count) { // Keep track of all dynamic table indices that this header block refers to so // that it can be passed to QpackBlockingManager. QpackBlockingManager::IndexSet referred_indices; // First pass: encode into |instructions|. - Instructions instructions = FirstPassEncode(header_list, &referred_indices); + Instructions instructions = FirstPassEncode(header_list, &referred_indices, + encoder_stream_sent_byte_count); const uint64_t required_insert_count = referred_indices.empty()
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h index 4aa69c1..d64d159 100644 --- a/quic/core/qpack/qpack_encoder.h +++ b/quic/core/qpack/qpack_encoder.h
@@ -49,9 +49,12 @@ QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate); ~QpackEncoder() override; - // Encode a header list. + // Encode a header list. If |encoder_stream_sent_byte_count| is not null, + // |*encoder_stream_sent_byte_count| will be set to the number of bytes sent + // on the encoder stream to insert dynamic table entries. std::string EncodeHeaderList(QuicStreamId stream_id, - const spdy::SpdyHeaderBlock& header_list); + const spdy::SpdyHeaderBlock& header_list, + QuicByteCount* encoder_stream_sent_byte_count); // Set maximum dynamic table capacity to |maximum_dynamic_table_capacity|, // measured in bytes. Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is @@ -121,13 +124,16 @@ // |*header_list| as a reference to an existing entry, the name of an existing // entry with a literal value, or a literal name and value pair. Sends // necessary instructions on the encoder stream. Records absolute indices of - // referred dynamic table entries in |*referred_indices|. Returns list of - // header field representations, with all dynamic table entries referred to - // with absolute indices. Returned Instructions object may have - // QuicStringPieces pointing to strings owned by |*header_list|. - Instructions FirstPassEncode( - const spdy::SpdyHeaderBlock& header_list, - QpackBlockingManager::IndexSet* referred_indices); + // referred dynamic table entries in |*referred_indices|. If + // |encoder_stream_sent_byte_count| is not null, then sets + // |*encoder_stream_sent_byte_count| to the number of bytes sent on the + // encoder stream to insert dynamic table entries. Returns list of header + // field representations, with all dynamic table entries referred to with + // absolute indices. Returned Instructions object may have QuicStringPieces + // pointing to strings owned by |*header_list|. + Instructions FirstPassEncode(const spdy::SpdyHeaderBlock& header_list, + QpackBlockingManager::IndexSet* referred_indices, + QuicByteCount* encoder_stream_sent_byte_count); // Performs second pass of two-pass encoding: serializes representations // generated in first pass, transforming absolute indices of dynamic table
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.cc b/quic/core/qpack/qpack_encoder_stream_sender.cc index e6209fd..533e3a1 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender.cc +++ b/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -15,7 +15,7 @@ QpackEncoderStreamSender::QpackEncoderStreamSender() : delegate_(nullptr) {} -void QpackEncoderStreamSender::SendInsertWithNameReference( +QuicByteCount QpackEncoderStreamSender::SendInsertWithNameReference( bool is_static, uint64_t name_index, QuicStringPiece value) { @@ -27,9 +27,10 @@ instruction_encoder_.Encode(InsertWithNameReferenceInstruction(), values_, &output); delegate_->WriteStreamData(output); + return output.size(); } -void QpackEncoderStreamSender::SendInsertWithoutNameReference( +QuicByteCount QpackEncoderStreamSender::SendInsertWithoutNameReference( QuicStringPiece name, QuicStringPiece value) { values_.name = name; @@ -39,23 +40,27 @@ instruction_encoder_.Encode(InsertWithoutNameReferenceInstruction(), values_, &output); delegate_->WriteStreamData(output); + return output.size(); } -void QpackEncoderStreamSender::SendDuplicate(uint64_t index) { +QuicByteCount QpackEncoderStreamSender::SendDuplicate(uint64_t index) { values_.varint = index; std::string output; instruction_encoder_.Encode(DuplicateInstruction(), values_, &output); delegate_->WriteStreamData(output); + return output.size(); } -void QpackEncoderStreamSender::SendSetDynamicTableCapacity(uint64_t capacity) { +QuicByteCount QpackEncoderStreamSender::SendSetDynamicTableCapacity( + uint64_t capacity) { values_.varint = capacity; std::string output; instruction_encoder_.Encode(SetDynamicTableCapacityInstruction(), values_, &output); delegate_->WriteStreamData(output); + return output.size(); } } // namespace quic
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.h b/quic/core/qpack/qpack_encoder_stream_sender.h index 3c410d5..c8c7717 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender.h +++ b/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -9,6 +9,7 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_encoder.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_stream_sender_delegate.h" +#include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" @@ -25,16 +26,16 @@ // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.2 // 5.2.1. Insert With Name Reference - void SendInsertWithNameReference(bool is_static, - uint64_t name_index, - QuicStringPiece value); + QuicByteCount SendInsertWithNameReference(bool is_static, + uint64_t name_index, + QuicStringPiece value); // 5.2.2. Insert Without Name Reference - void SendInsertWithoutNameReference(QuicStringPiece name, - QuicStringPiece value); + QuicByteCount SendInsertWithoutNameReference(QuicStringPiece name, + QuicStringPiece value); // 5.2.3. Duplicate - void SendDuplicate(uint64_t index); + QuicByteCount SendDuplicate(uint64_t index); // 5.2.4. Set Dynamic Table Capacity - void SendSetDynamicTableCapacity(uint64_t capacity); + QuicByteCount SendSetDynamicTableCapacity(uint64_t capacity); // delegate must be set if dynamic table capacity is not zero. void set_qpack_stream_sender_delegate(QpackStreamSenderDelegate* delegate) {
diff --git a/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/quic/core/qpack/qpack_encoder_stream_sender_test.cc index 4a15d1f..dcfd5bd 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender_test.cc +++ b/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -28,80 +28,93 @@ TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) { // Static, index fits in prefix, empty value. - EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("c500")))); - stream_.SendInsertWithNameReference(true, 5, ""); + std::string expected_encoded_data = QuicTextUtils::HexDecode("c500"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithNameReference(true, 5, "")); // Static, index fits in prefix, Huffman encoded value. - EXPECT_CALL(delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode("c28294e7")))); - stream_.SendInsertWithNameReference(true, 2, "foo"); + expected_encoded_data = QuicTextUtils::HexDecode("c28294e7"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithNameReference(true, 2, "foo")); // Not static, index does not fit in prefix, not Huffman encoded value. - EXPECT_CALL(delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode("bf4a03626172")))); - stream_.SendInsertWithNameReference(false, 137, "bar"); + expected_encoded_data = QuicTextUtils::HexDecode("bf4a03626172"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithNameReference(false, 137, "bar")); // Value length does not fit in prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. - EXPECT_CALL( - delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")))); - stream_.SendInsertWithNameReference(false, 42, std::string(127, 'Z')); + expected_encoded_data = QuicTextUtils::HexDecode( + "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ( + expected_encoded_data.size(), + stream_.SendInsertWithNameReference(false, 42, std::string(127, 'Z'))); } TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) { // Empty name and value. - EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("4000")))); - stream_.SendInsertWithoutNameReference("", ""); + std::string expected_encoded_data = QuicTextUtils::HexDecode("4000"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithoutNameReference("", "")); // Huffman encoded short strings. - EXPECT_CALL(delegate_, WriteStreamData( - Eq(QuicTextUtils::HexDecode("4362617203626172")))); - stream_.SendInsertWithoutNameReference("bar", "bar"); + expected_encoded_data = QuicTextUtils::HexDecode("4362617203626172"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithoutNameReference("bar", "bar")); // Not Huffman encoded short strings. - EXPECT_CALL(delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode("6294e78294e7")))); - stream_.SendInsertWithoutNameReference("foo", "foo"); + expected_encoded_data = QuicTextUtils::HexDecode("6294e78294e7"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithoutNameReference("foo", "foo")); // Not Huffman encoded long strings; length does not fit on prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. - EXPECT_CALL( - delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f" - "005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" - "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")))); - stream_.SendInsertWithoutNameReference(std::string(31, 'Z'), - std::string(127, 'Z')); + expected_encoded_data = QuicTextUtils::HexDecode( + "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f" + "005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" + "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendInsertWithoutNameReference(std::string(31, 'Z'), + std::string(127, 'Z'))); } TEST_F(QpackEncoderStreamSenderTest, Duplicate) { // Small index fits in prefix. - EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("11")))); - stream_.SendDuplicate(17); + std::string expected_encoded_data = QuicTextUtils::HexDecode("11"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), stream_.SendDuplicate(17)); // Large index requires two extension bytes. - EXPECT_CALL(delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode("1fd503")))); - stream_.SendDuplicate(500); + expected_encoded_data = QuicTextUtils::HexDecode("1fd503"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), stream_.SendDuplicate(500)); } TEST_F(QpackEncoderStreamSenderTest, SetDynamicTableCapacity) { // Small capacity fits in prefix. - EXPECT_CALL(delegate_, WriteStreamData(Eq(QuicTextUtils::HexDecode("31")))); - stream_.SendSetDynamicTableCapacity(17); + std::string expected_encoded_data = QuicTextUtils::HexDecode("31"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendSetDynamicTableCapacity(17)); // Large capacity requires two extension bytes. - EXPECT_CALL(delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode("3fd503")))); - stream_.SendSetDynamicTableCapacity(500); + expected_encoded_data = QuicTextUtils::HexDecode("3fd503"); + EXPECT_CALL(delegate_, WriteStreamData(Eq(expected_encoded_data))); + EXPECT_EQ(expected_encoded_data.size(), + stream_.SendSetDynamicTableCapacity(500)); } } // namespace
diff --git a/quic/core/qpack/qpack_encoder_test.cc b/quic/core/qpack/qpack_encoder_test.cc index 0da6f3e..f230942 100644 --- a/quic/core/qpack/qpack_encoder_test.cc +++ b/quic/core/qpack/qpack_encoder_test.cc
@@ -25,7 +25,9 @@ class QpackEncoderTest : public QuicTest { protected: - QpackEncoderTest() : encoder_(&decoder_stream_error_delegate_) { + QpackEncoderTest() + : encoder_(&decoder_stream_error_delegate_), + encoder_stream_sent_byte_count_(0) { encoder_.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate_); encoder_.SetMaximumBlockedStreams(1); } @@ -33,12 +35,14 @@ ~QpackEncoderTest() override = default; std::string Encode(const spdy::SpdyHeaderBlock& header_list) { - return encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list); + return encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list, + &encoder_stream_sent_byte_count_); } StrictMock<MockDecoderStreamErrorDelegate> decoder_stream_error_delegate_; StrictMock<MockQpackStreamSenderDelegate> encoder_stream_sender_delegate_; QpackEncoder encoder_; + QuicByteCount encoder_stream_sent_byte_count_; }; TEST_F(QpackEncoderTest, Empty) { @@ -199,24 +203,32 @@ header_list["cookie"] = "baz"; // name matches static entry // Insert three entries into the dynamic table. + std::string insert_entry1 = QuicTextUtils::HexDecode( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172"); // value "bar" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "62" // insert without name reference - "94e7" // Huffman-encoded name "foo" - "03626172")))); // value "bar" + WriteStreamData(Eq(insert_entry1))); + + std::string insert_entry2 = QuicTextUtils::HexDecode( + "80" // insert with name reference, dynamic index 0 + "0362617a"); // value "baz" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "80" // insert with name reference, dynamic index 0 - "0362617a")))); // value "baz" + WriteStreamData(Eq(insert_entry2))); + + std::string insert_entry3 = QuicTextUtils::HexDecode( + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "c5" // insert with name reference, static index 5 - "0362617a")))); // value "baz" + WriteStreamData(Eq(insert_entry3))); EXPECT_EQ(QuicTextUtils::HexDecode( "0400" // prefix "828180"), // dynamic entries with relative index 0, 1, and 2 Encode(header_list)); + + EXPECT_EQ(insert_entry1.size() + insert_entry2.size() + insert_entry3.size(), + encoder_stream_sent_byte_count_); } // There is no room in the dynamic table after inserting the first entry. @@ -237,11 +249,12 @@ header_list["bar"] = "baz"; // no match // Insert one entry into the dynamic table. + std::string insert_entry = QuicTextUtils::HexDecode( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172"); // value "bar" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "62" // insert without name reference - "94e7" // Huffman-encoded name "foo" - "03626172")))); // value "bar" + WriteStreamData(Eq(insert_entry))); EXPECT_EQ(QuicTextUtils::HexDecode("0200" // prefix "80" // dynamic entry 0 @@ -252,6 +265,8 @@ "23626172" // literal name "bar" "0362617a"), // with literal value "baz" Encode(header_list)); + + EXPECT_EQ(insert_entry.size(), encoder_stream_sent_byte_count_); } TEST_F(QpackEncoderTest, BlockedStream) { @@ -267,15 +282,18 @@ header_list1["foo"] = "bar"; // Insert one entry into the dynamic table. + std::string insert_entry1 = QuicTextUtils::HexDecode( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172"); // value "bar" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "62" // insert without name reference - "94e7" // Huffman-encoded name "foo" - "03626172")))); // value "bar" + WriteStreamData(Eq(insert_entry1))); EXPECT_EQ(QuicTextUtils::HexDecode("0200" // prefix "80"), // dynamic entry 0 - encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list1)); + encoder_.EncodeHeaderList(/* stream_id = */ 1, header_list1, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(insert_entry1.size(), encoder_stream_sent_byte_count_); // Stream 1 is blocked. Stream 2 is not allowed to block. spdy::SpdyHeaderBlock header_list2; @@ -294,29 +312,40 @@ "0362617a" // with literal value "baz" "23626172" // literal name "bar" "0362617a"), // with literal value "baz" - encoder_.EncodeHeaderList(/* stream_id = */ 2, header_list2)); + encoder_.EncodeHeaderList(/* stream_id = */ 2, header_list2, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); // Peer acknowledges receipt of one dynamic table entry. // Stream 1 is no longer blocked. encoder_.OnInsertCountIncrement(1); // Insert three entries into the dynamic table. + std::string insert_entry2 = QuicTextUtils::HexDecode( + "80" // insert with name reference, dynamic index 0 + "0362617a"); // value "baz" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "80" // insert with name reference, dynamic index 0 - "0362617a")))); // value "baz" + WriteStreamData(Eq(insert_entry2))); + + std::string insert_entry3 = QuicTextUtils::HexDecode( + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "c5" // insert with name reference, static index 5 - "0362617a")))); // value "baz" + WriteStreamData(Eq(insert_entry3))); + + std::string insert_entry4 = QuicTextUtils::HexDecode( + "43" // insert without name reference + "626172" // name "bar" + "0362617a"); // value "baz" EXPECT_CALL(encoder_stream_sender_delegate_, - WriteStreamData(Eq(QuicTextUtils::HexDecode( - "43" // insert without name reference - "626172" // name "bar" - "0362617a")))); // value "baz" - EXPECT_EQ(QuicTextUtils::HexDecode("0500" // prefix + WriteStreamData(Eq(insert_entry4))); + + EXPECT_EQ(QuicTextUtils::HexDecode("0500" // prefix "83828180"), // dynamic entries - encoder_.EncodeHeaderList(/* stream_id = */ 3, header_list2)); + encoder_.EncodeHeaderList(/* stream_id = */ 3, header_list2, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(insert_entry2.size() + insert_entry3.size() + insert_entry4.size(), + encoder_stream_sent_byte_count_); // Stream 3 is blocked. Stream 4 is not allowed to block, but it can // reference already acknowledged dynamic entry 0. @@ -328,7 +357,9 @@ "0362617a" // with literal value "baz" "23626172" // literal name "bar" "0362617a"), // with literal value "baz" - encoder_.EncodeHeaderList(/* stream_id = */ 4, header_list2)); + encoder_.EncodeHeaderList(/* stream_id = */ 4, header_list2, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); // Peer acknowledges receipt of two more dynamic table entries. // Stream 3 is still blocked. @@ -340,7 +371,9 @@ "828180" // dynamic entries "23626172" // literal name "bar" "0362617a"), // with literal value "baz" - encoder_.EncodeHeaderList(/* stream_id = */ 5, header_list2)); + encoder_.EncodeHeaderList(/* stream_id = */ 5, header_list2, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); // Peer acknowledges decoding header block on stream 3. // Stream 3 is not blocked any longer. @@ -348,7 +381,9 @@ EXPECT_EQ(QuicTextUtils::HexDecode("0500" // prefix "83828180"), // dynamic entries - encoder_.EncodeHeaderList(/* stream_id = */ 6, header_list2)); + encoder_.EncodeHeaderList(/* stream_id = */ 6, header_list2, + &encoder_stream_sent_byte_count_)); + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); } TEST_F(QpackEncoderTest, Draining) {
diff --git a/quic/core/qpack/qpack_round_trip_test.cc b/quic/core/qpack/qpack_round_trip_test.cc index 9441b82..beff68e 100644 --- a/quic/core/qpack/qpack_round_trip_test.cc +++ b/quic/core/qpack/qpack_round_trip_test.cc
@@ -32,7 +32,7 @@ QpackEncoder encoder(&decoder_stream_error_delegate); encoder.set_qpack_stream_sender_delegate(&encoder_stream_sender_delegate); std::string encoded_header_block = - encoder.EncodeHeaderList(/* stream_id = */ 1, header_list); + encoder.EncodeHeaderList(/* stream_id = */ 1, header_list, nullptr); TestHeadersHandler handler; NoopEncoderStreamErrorDelegate encoder_stream_error_delegate;