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