Add QpackBlockingManager to track blocked streams and blocking entries.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 260829566
Change-Id: I3f2f74384f213f3dfea8460a77f759b070a7d79c
diff --git a/quic/core/qpack/qpack_blocking_manager_test.cc b/quic/core/qpack/qpack_blocking_manager_test.cc
new file mode 100644
index 0000000..a7cba73
--- /dev/null
+++ b/quic/core/qpack/qpack_blocking_manager_test.cc
@@ -0,0 +1,211 @@
+// 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());
+}
+
+} // namespace
+} // namespace test
+} // namespace quic