| // Copyright (c) 2018 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/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h" |
| |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" |
| |
| using testing::Eq; |
| using testing::StrictMock; |
| |
| namespace quic { |
| namespace test { |
| namespace { |
| |
| class MockDelegate : public QpackEncoderStreamReceiver::Delegate { |
| public: |
| ~MockDelegate() override = default; |
| |
| MOCK_METHOD3(OnInsertWithNameReference, |
| void(bool is_static, |
| uint64_t name_index, |
| QuicStringPiece value)); |
| MOCK_METHOD2(OnInsertWithoutNameReference, |
| void(QuicStringPiece name, QuicStringPiece value)); |
| MOCK_METHOD1(OnDuplicate, void(uint64_t index)); |
| MOCK_METHOD1(OnSetDynamicTableCapacity, void(uint64_t capacity)); |
| MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message)); |
| }; |
| |
| class QpackEncoderStreamReceiverTest : public QuicTest { |
| protected: |
| QpackEncoderStreamReceiverTest() : stream_(&delegate_) {} |
| ~QpackEncoderStreamReceiverTest() override = default; |
| |
| void Decode(QuicStringPiece data) { stream_.Decode(data); } |
| StrictMock<MockDelegate>* delegate() { return &delegate_; } |
| |
| private: |
| QpackEncoderStreamReceiver stream_; |
| StrictMock<MockDelegate> delegate_; |
| }; |
| |
| TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) { |
| // Static, index fits in prefix, empty value. |
| EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, Eq(""))); |
| // Static, index fits in prefix, Huffman encoded value. |
| EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, Eq("foo"))); |
| // Not static, index does not fit in prefix, not Huffman encoded value. |
| EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, Eq("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(), |
| OnInsertWithNameReference(false, 42, Eq(std::string(127, 'Z')))); |
| |
| Decode(QuicTextUtils::HexDecode( |
| "c500" |
| "c28294e7" |
| "bf4a03626172" |
| "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("bfffffffffffffffffffffff")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) { |
| // Empty name and value. |
| EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq(""))); |
| // Huffman encoded short strings. |
| EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar"))); |
| // Not Huffman encoded short strings. |
| EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("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(), |
| OnInsertWithoutNameReference(Eq(std::string(31, 'Z')), |
| Eq(std::string(127, 'Z')))); |
| |
| Decode(QuicTextUtils::HexDecode( |
| "4000" |
| "4362617203626172" |
| "6294e78294e7" |
| "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f005a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" |
| "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a")); |
| } |
| |
| // Name Length value is too large for varint decoder to decode. |
| TEST_F(QpackEncoderStreamReceiverTest, |
| InsertWithoutNameReferenceNameTooLongForVarintDecoder) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff")); |
| } |
| |
| // Name Length value can be decoded by varint decoder but exceeds 1 MB limit. |
| TEST_F(QpackEncoderStreamReceiverTest, |
| InsertWithoutNameReferenceNameExceedsLimit) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long."))); |
| |
| Decode(QuicTextUtils::HexDecode("5fffff7f")); |
| } |
| |
| // Value Length value is too large for varint decoder to decode. |
| TEST_F(QpackEncoderStreamReceiverTest, |
| InsertWithoutNameReferenceValueTooLongForVarintDecoder) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff")); |
| } |
| |
| // Value Length value can be decoded by varint decoder but exceeds 1 MB limit. |
| TEST_F(QpackEncoderStreamReceiverTest, |
| InsertWithoutNameReferenceValueExceedsLimit) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long."))); |
| |
| Decode(QuicTextUtils::HexDecode("436261727fffff7f")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, Duplicate) { |
| // Small index fits in prefix. |
| EXPECT_CALL(*delegate(), OnDuplicate(17)); |
| // Large index requires two extension bytes. |
| EXPECT_CALL(*delegate(), OnDuplicate(500)); |
| |
| Decode(QuicTextUtils::HexDecode("111fd503")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("1fffffffffffffffffffff")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) { |
| // Small capacity fits in prefix. |
| EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(17)); |
| // Large capacity requires two extension bytes. |
| EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500)); |
| |
| Decode(QuicTextUtils::HexDecode("313fd503")); |
| } |
| |
| TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) { |
| EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); |
| |
| Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace quic |