diff options
Diffstat (limited to 'chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc')
-rw-r--r-- | chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc index 21397ed8571..30f578e9378 100644 --- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc +++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test.cc @@ -18,12 +18,19 @@ using ::testing::_; using ::testing::Eq; +using ::testing::Return; using ::testing::StrictMock; namespace quic { namespace test { namespace { +// A number larger than kMaxBytesBufferedByStream in +// qpack_encoder_stream_sender.cc. Returning this value from NumBytesBuffered() +// will instruct QpackEncoder not to generate any instructions for the encoder +// stream. +constexpr uint64_t kTooManyBytesBuffered = 1024 * 1024; + class QpackEncoderTest : public QuicTest { protected: QpackEncoderTest() @@ -47,6 +54,8 @@ class QpackEncoderTest : public QuicTest { }; TEST_F(QpackEncoderTest, Empty) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; std::string output = Encode(header_list); @@ -54,6 +63,8 @@ TEST_F(QpackEncoderTest, Empty) { } TEST_F(QpackEncoderTest, EmptyName) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list[""] = "foo"; std::string output = Encode(header_list); @@ -62,6 +73,8 @@ TEST_F(QpackEncoderTest, EmptyName) { } TEST_F(QpackEncoderTest, EmptyValue) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = ""; std::string output = Encode(header_list); @@ -70,6 +83,8 @@ TEST_F(QpackEncoderTest, EmptyValue) { } TEST_F(QpackEncoderTest, EmptyNameAndValue) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list[""] = ""; std::string output = Encode(header_list); @@ -78,6 +93,8 @@ TEST_F(QpackEncoderTest, EmptyNameAndValue) { } TEST_F(QpackEncoderTest, Simple) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = "bar"; std::string output = Encode(header_list); @@ -86,6 +103,8 @@ TEST_F(QpackEncoderTest, Simple) { } TEST_F(QpackEncoderTest, Multiple) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = "bar"; // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. @@ -108,6 +127,8 @@ TEST_F(QpackEncoderTest, Multiple) { } TEST_F(QpackEncoderTest, StaticTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); { spdy::Http2HeaderBlock header_list; header_list[":method"] = "GET"; @@ -149,6 +170,8 @@ TEST_F(QpackEncoderTest, DecoderStreamError) { } TEST_F(QpackEncoderTest, SplitAlongNullCharacter) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list; header_list["foo"] = absl::string_view("bar\0bar\0baz", 11); std::string output = Encode(header_list); @@ -217,6 +240,8 @@ TEST_F(QpackEncoderTest, InvalidHeaderAcknowledgement) { } TEST_F(QpackEncoderTest, DynamicTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(4096); encoder_.SetDynamicTableCapacity(4096); @@ -252,6 +277,8 @@ TEST_F(QpackEncoderTest, DynamicTable) { // There is no room in the dynamic table after inserting the first entry. TEST_F(QpackEncoderTest, SmallDynamicTable) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(QpackEntry::Size("foo", "bar")); encoder_.SetDynamicTableCapacity(QpackEntry::Size("foo", "bar")); @@ -288,6 +315,8 @@ TEST_F(QpackEncoderTest, SmallDynamicTable) { } TEST_F(QpackEncoderTest, BlockedStream) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); encoder_.SetMaximumBlockedStreams(1); encoder_.SetMaximumDynamicTableCapacity(4096); encoder_.SetDynamicTableCapacity(4096); @@ -395,6 +424,8 @@ TEST_F(QpackEncoderTest, BlockedStream) { } TEST_F(QpackEncoderTest, Draining) { + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); spdy::Http2HeaderBlock header_list1; header_list1["one"] = "foo"; header_list1["two"] = "foo"; @@ -467,6 +498,135 @@ TEST_F(QpackEncoderTest, DynamicTableCapacityLessThanMaximum) { EXPECT_EQ(30u, header_table->dynamic_table_capacity()); } +TEST_F(QpackEncoderTest, EncoderStreamWritesDisallowedThenAllowed) { + if (!GetQuicReloadableFlag(quic_limit_encoder_stream_buffering)) { + return; + } + + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(kTooManyBytesBuffered)); + encoder_.SetMaximumBlockedStreams(1); + encoder_.SetMaximumDynamicTableCapacity(4096); + encoder_.SetDynamicTableCapacity(4096); + + spdy::Http2HeaderBlock header_list1; + header_list1["foo"] = "bar"; + header_list1.AppendValueOrAddHeader("foo", "baz"); + header_list1["cookie"] = "baz"; // name matches static entry + + // Encoder is not allowed to write on the encoder stream. + // No Set Dynamic Table Capacity or Insert instructions are sent. + // Headers are encoded as string literals. + EXPECT_EQ(absl::HexStringToBytes("0000" // prefix + "2a94e7" // literal name "foo" + "03626172" // with literal value "bar" + "2a94e7" // literal name "foo" + "0362617a" // with literal value "baz" + "55" // name of static entry 5 + "0362617a"), // with literal value "baz" + Encode(header_list1)); + + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); + + // If number of bytes buffered by encoder stream goes under the threshold, + // then QpackEncoder will resume emitting encoder stream instructions. + ::testing::Mock::VerifyAndClearExpectations(&encoder_stream_sender_delegate_); + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); + + spdy::Http2HeaderBlock header_list2; + header_list2["foo"] = "bar"; + header_list2.AppendValueOrAddHeader("foo", + "baz"); // name matches dynamic entry + header_list2["cookie"] = "baz"; // name matches static entry + + // Set Dynamic Table Capacity instruction. + std::string set_dyanamic_table_capacity = absl::HexStringToBytes("3fe11f"); + // Insert three entries into the dynamic table. + std::string insert_entries = absl::HexStringToBytes( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172" // value "bar" + "80" // insert with name reference, dynamic index 0 + "0362617a" // value "baz" + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" + EXPECT_CALL(encoder_stream_sender_delegate_, + WriteStreamData(Eq( + absl::StrCat(set_dyanamic_table_capacity, insert_entries)))); + + EXPECT_EQ(absl::HexStringToBytes( + "0400" // prefix + "828180"), // dynamic entries with relative index 0, 1, and 2 + Encode(header_list2)); + + EXPECT_EQ(insert_entries.size(), encoder_stream_sent_byte_count_); +} + +TEST_F(QpackEncoderTest, EncoderStreamWritesAllowedThenDisallowed) { + if (!GetQuicReloadableFlag(quic_limit_encoder_stream_buffering)) { + return; + } + + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(0)); + encoder_.SetMaximumBlockedStreams(1); + encoder_.SetMaximumDynamicTableCapacity(4096); + encoder_.SetDynamicTableCapacity(4096); + + spdy::Http2HeaderBlock header_list1; + header_list1["foo"] = "bar"; + header_list1.AppendValueOrAddHeader("foo", + "baz"); // name matches dynamic entry + header_list1["cookie"] = "baz"; // name matches static entry + + // Set Dynamic Table Capacity instruction. + std::string set_dyanamic_table_capacity = absl::HexStringToBytes("3fe11f"); + // Insert three entries into the dynamic table. + std::string insert_entries = absl::HexStringToBytes( + "62" // insert without name reference + "94e7" // Huffman-encoded name "foo" + "03626172" // value "bar" + "80" // insert with name reference, dynamic index 0 + "0362617a" // value "baz" + "c5" // insert with name reference, static index 5 + "0362617a"); // value "baz" + EXPECT_CALL(encoder_stream_sender_delegate_, + WriteStreamData(Eq( + absl::StrCat(set_dyanamic_table_capacity, insert_entries)))); + + EXPECT_EQ(absl::HexStringToBytes( + "0400" // prefix + "828180"), // dynamic entries with relative index 0, 1, and 2 + Encode(header_list1)); + + EXPECT_EQ(insert_entries.size(), encoder_stream_sent_byte_count_); + + // If number of bytes buffered by encoder stream goes over the threshold, + // then QpackEncoder will stop emitting encoder stream instructions. + ::testing::Mock::VerifyAndClearExpectations(&encoder_stream_sender_delegate_); + EXPECT_CALL(encoder_stream_sender_delegate_, NumBytesBuffered()) + .WillRepeatedly(Return(kTooManyBytesBuffered)); + + spdy::Http2HeaderBlock header_list2; + header_list2["foo"] = "bar"; // matches previously inserted dynamic entry + header_list2["bar"] = "baz"; + header_list2["cookie"] = "baz"; // name matches static entry + + // Encoder is not allowed to write on the encoder stream. + // No Set Dynamic Table Capacity or Insert instructions are sent. + // Headers are encoded as string literals. + EXPECT_EQ( + absl::HexStringToBytes("0400" // prefix + "82" // dynamic entry with relative index 0 + "23626172" // literal name "bar" + "0362617a" // with literal value "baz" + "80"), // dynamic entry with relative index 2 + Encode(header_list2)); + + EXPECT_EQ(0u, encoder_stream_sent_byte_count_); +} + } // namespace } // namespace test } // namespace quic |