| // Copyright (c) 2019 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_blocking_manager.h" |
| |
| #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" |
| |
| namespace quic { |
| namespace test { |
| namespace { |
| |
| class QpackBlockingManagerTest : public QuicTest { |
| protected: |
| QpackBlockingManagerTest() = default; |
| ~QpackBlockingManagerTest() override = default; |
| |
| QpackBlockingManager manager_; |
| }; |
| |
| TEST_F(QpackBlockingManagerTest, Empty) { |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| EXPECT_FALSE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_FALSE(manager_.OnHeaderAcknowledgement(1)); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, NotBlockedByInsertCountIncrement) { |
| manager_.OnInsertCountIncrement(2); |
| |
| // Stream 0 is not blocked, because it only references entries that are |
| // already acknowledged by an Insert Count Increment instruction. |
| manager_.OnHeaderBlockSent(0, {1, 0}); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, UnblockedByInsertCountIncrement) { |
| manager_.OnHeaderBlockSent(0, {1, 0}); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| |
| manager_.OnInsertCountIncrement(2); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, NotBlockedByHeaderAcknowledgement) { |
| manager_.OnHeaderBlockSent(0, {2, 1, 1}); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| |
| // Stream 1 is not blocked, because it only references entries that are |
| // already acknowledged by a Header Acknowledgement instruction. |
| manager_.OnHeaderBlockSent(1, {2, 2}); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, UnblockedByHeaderAcknowledgement) { |
| manager_.OnHeaderBlockSent(0, {2, 1, 1}); |
| manager_.OnHeaderBlockSent(1, {2, 2}); |
| EXPECT_EQ(2u, manager_.blocked_stream_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, KnownReceivedCount) { |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| |
| // Sending a header block does not change Known Received Count. |
| manager_.OnHeaderBlockSent(0, {0}); |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| |
| manager_.OnHeaderBlockSent(1, {1}); |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| |
| // Header Acknowledgement might increase Known Received Count. |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(1u, manager_.known_received_count()); |
| |
| manager_.OnHeaderBlockSent(2, {5}); |
| EXPECT_EQ(1u, manager_.known_received_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(1)); |
| EXPECT_EQ(2u, manager_.known_received_count()); |
| |
| // Insert Count Increment increases Known Received Count. |
| manager_.OnInsertCountIncrement(2); |
| EXPECT_EQ(4u, manager_.known_received_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(2)); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| |
| // Stream Cancellation does not change Known Received Count. |
| manager_.OnStreamCancellation(0); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| |
| // Header Acknowledgement of a block with smaller Required Insert Count does |
| // not increase Known Received Count. |
| manager_.OnHeaderBlockSent(0, {3}); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| |
| // Header Acknowledgement of a block with equal Required Insert Count does not |
| // increase Known Received Count. |
| manager_.OnHeaderBlockSent(1, {5}); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(1)); |
| EXPECT_EQ(6u, manager_.known_received_count()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, SmallestBlockingIndex) { |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(0, {0}); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(1, {2}); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(2u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(1, {1}); |
| EXPECT_EQ(1u, manager_.smallest_blocking_index()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(1)); |
| EXPECT_EQ(1u, manager_.smallest_blocking_index()); |
| |
| // Insert Count Increment does not change smallest blocking index. |
| manager_.OnInsertCountIncrement(2); |
| EXPECT_EQ(1u, manager_.smallest_blocking_index()); |
| |
| manager_.OnStreamCancellation(1); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, HeaderAcknowledgementsOnSingleStream) { |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(0, {2, 1, 1}); |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(1u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(0, {1, 0}); |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(3u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(0, {3}); |
| EXPECT_EQ(3u, manager_.known_received_count()); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(3u, manager_.known_received_count()); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(3u, manager_.smallest_blocking_index()); |
| |
| EXPECT_TRUE(manager_.OnHeaderAcknowledgement(0)); |
| EXPECT_EQ(4u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| EXPECT_FALSE(manager_.OnHeaderAcknowledgement(0)); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, CancelStream) { |
| manager_.OnHeaderBlockSent(0, {3}); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(3u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(0, {2}); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(2u, manager_.smallest_blocking_index()); |
| |
| manager_.OnHeaderBlockSent(1, {4}); |
| EXPECT_EQ(2u, manager_.blocked_stream_count()); |
| EXPECT_EQ(2u, manager_.smallest_blocking_index()); |
| |
| manager_.OnStreamCancellation(0); |
| EXPECT_EQ(1u, manager_.blocked_stream_count()); |
| EXPECT_EQ(4u, manager_.smallest_blocking_index()); |
| |
| manager_.OnStreamCancellation(1); |
| EXPECT_EQ(0u, manager_.blocked_stream_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, |
| ReferenceOnEncoderStreamUnblockedByInsertCountIncrement) { |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| // Entry 1 refers to entry 0. |
| manager_.OnReferenceSentOnEncoderStream(1, 0); |
| // Entry 2 also refers to entry 0. |
| manager_.OnReferenceSentOnEncoderStream(2, 0); |
| |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| // Acknowledging entry 1 still leaves one unacknowledged reference to entry 0. |
| manager_.OnInsertCountIncrement(2); |
| |
| EXPECT_EQ(2u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| // Entry 3 also refers to entry 2. |
| manager_.OnReferenceSentOnEncoderStream(3, 2); |
| |
| EXPECT_EQ(2u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| // Acknowledging entry 2 removes last reference to entry 0. |
| manager_.OnInsertCountIncrement(1); |
| |
| EXPECT_EQ(3u, manager_.known_received_count()); |
| EXPECT_EQ(2u, manager_.smallest_blocking_index()); |
| |
| // Acknowledging entry 4 (and implicitly 3) removes reference to entry 2. |
| manager_.OnInsertCountIncrement(2); |
| |
| EXPECT_EQ(5u, manager_.known_received_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| } |
| |
| TEST_F(QpackBlockingManagerTest, |
| ReferenceOnEncoderStreamUnblockedByHeaderAcknowledgement) { |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| |
| // Entry 1 refers to entry 0. |
| manager_.OnReferenceSentOnEncoderStream(1, 0); |
| // Entry 2 also refers to entry 0. |
| manager_.OnReferenceSentOnEncoderStream(2, 0); |
| |
| EXPECT_EQ(0u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| // Acknowledging a header block with entries up to 1 still leave one |
| // unacknowledged reference to entry 0. |
| manager_.OnHeaderBlockSent(/* stream_id = */ 0, {0, 1}); |
| manager_.OnHeaderAcknowledgement(/* stream_id = */ 0); |
| |
| EXPECT_EQ(2u, manager_.known_received_count()); |
| EXPECT_EQ(0u, manager_.smallest_blocking_index()); |
| |
| // Entry 3 also refers to entry 2. |
| manager_.OnReferenceSentOnEncoderStream(3, 2); |
| |
| // Acknowledging a header block with entries up to 2 removes last reference to |
| // entry 0. |
| manager_.OnHeaderBlockSent(/* stream_id = */ 0, {2, 0, 2}); |
| manager_.OnHeaderAcknowledgement(/* stream_id = */ 0); |
| |
| EXPECT_EQ(3u, manager_.known_received_count()); |
| EXPECT_EQ(2u, manager_.smallest_blocking_index()); |
| |
| // Acknowledging entry 4 (and implicitly 3) removes reference to entry 2. |
| manager_.OnHeaderBlockSent(/* stream_id = */ 0, {1, 4, 2, 0}); |
| manager_.OnHeaderAcknowledgement(/* stream_id = */ 0); |
| |
| EXPECT_EQ(5u, manager_.known_received_count()); |
| EXPECT_EQ(std::numeric_limits<uint64_t>::max(), |
| manager_.smallest_blocking_index()); |
| } |
| |
| } // namespace |
| } // namespace test |
| } // namespace quic |