Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_received_packet_manager_test.cc b/quic/core/quic_received_packet_manager_test.cc
new file mode 100644
index 0000000..0512cb7
--- /dev/null
+++ b/quic/core/quic_received_packet_manager_test.cc
@@ -0,0 +1,807 @@
+// Copyright 2013 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/quic_received_packet_manager.h"
+
+#include <algorithm>
+#include <ostream>
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+
+namespace quic {
+namespace test {
+
+class QuicReceivedPacketManagerPeer {
+ public:
+  static void SetAckMode(QuicReceivedPacketManager* manager, AckMode ack_mode) {
+    manager->ack_mode_ = ack_mode;
+  }
+
+  static void SetFastAckAfterQuiescence(QuicReceivedPacketManager* manager,
+                                        bool fast_ack_after_quiescence) {
+    manager->fast_ack_after_quiescence_ = fast_ack_after_quiescence;
+  }
+
+  static void SetAckDecimationDelay(QuicReceivedPacketManager* manager,
+                                    float ack_decimation_delay) {
+    manager->ack_decimation_delay_ = ack_decimation_delay;
+  }
+};
+
+namespace {
+
+const bool kInstigateAck = true;
+const QuicTime::Delta kMinRttMs = QuicTime::Delta::FromMilliseconds(40);
+const QuicTime::Delta kDelayedAckTime =
+    QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+struct TestParams {
+  explicit TestParams(QuicTransportVersion version) : version(version) {}
+
+  friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
+    os << "{ version: " << QuicVersionToString(p.version) << " }";
+    return os;
+  }
+
+  QuicTransportVersion version;
+};
+
+std::vector<TestParams> GetTestParams() {
+  std::vector<TestParams> params;
+  QuicTransportVersionVector all_supported_versions =
+      AllSupportedTransportVersions();
+  for (size_t i = 0; i < all_supported_versions.size(); ++i) {
+    params.push_back(TestParams(all_supported_versions[i]));
+  }
+  return params;
+}
+
+class QuicReceivedPacketManagerTest : public QuicTestWithParam<TestParams> {
+ protected:
+  QuicReceivedPacketManagerTest() : received_manager_(&stats_) {
+    clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+    rtt_stats_.UpdateRtt(kMinRttMs, QuicTime::Delta::Zero(), QuicTime::Zero());
+    received_manager_.set_save_timestamps(true);
+  }
+
+  void RecordPacketReceipt(uint64_t packet_number) {
+    RecordPacketReceipt(packet_number, QuicTime::Zero());
+  }
+
+  void RecordPacketReceipt(uint64_t packet_number, QuicTime receipt_time) {
+    QuicPacketHeader header;
+    header.packet_number = QuicPacketNumber(packet_number);
+    received_manager_.RecordPacketReceived(header, receipt_time);
+  }
+
+  bool HasPendingAck() {
+    DCHECK(received_manager_.decide_when_to_send_acks());
+    return received_manager_.ack_timeout().IsInitialized();
+  }
+
+  void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks,
+                             uint64_t last_received_packet_number) {
+    DCHECK(received_manager_.decide_when_to_send_acks());
+    received_manager_.MaybeUpdateAckTimeout(
+        should_last_packet_instigate_acks,
+        QuicPacketNumber(last_received_packet_number), clock_.ApproximateNow(),
+        clock_.ApproximateNow(), &rtt_stats_, kDelayedAckTime);
+  }
+
+  void CheckAckTimeout(QuicTime time) {
+    DCHECK(HasPendingAck() && received_manager_.ack_timeout() == time);
+    if (time <= clock_.ApproximateNow()) {
+      // ACK timeout expires, send an ACK.
+      received_manager_.ResetAckStates();
+      DCHECK(!HasPendingAck());
+    }
+  }
+
+  MockClock clock_;
+  RttStats rtt_stats_;
+  QuicConnectionStats stats_;
+  QuicReceivedPacketManager received_manager_;
+};
+
+INSTANTIATE_TEST_SUITE_P(QuicReceivedPacketManagerTest,
+                         QuicReceivedPacketManagerTest,
+                         ::testing::ValuesIn(GetTestParams()));
+
+TEST_P(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
+  QuicPacketHeader header;
+  header.packet_number = QuicPacketNumber(2u);
+  received_manager_.RecordPacketReceived(header, QuicTime::Zero());
+  header.packet_number = QuicPacketNumber(7u);
+  received_manager_.RecordPacketReceived(header, QuicTime::Zero());
+  EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u)));
+  EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u)));
+  received_manager_.DontWaitForPacketsBefore(QuicPacketNumber(4));
+  EXPECT_FALSE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u)));
+  EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u)));
+}
+
+TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) {
+  QuicPacketHeader header;
+  header.packet_number = QuicPacketNumber(2u);
+  QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2);
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  received_manager_.RecordPacketReceived(header, two_ms);
+  EXPECT_TRUE(received_manager_.ack_frame_updated());
+
+  QuicFrame ack = received_manager_.GetUpdatedAckFrame(QuicTime::Zero());
+  if (received_manager_.decide_when_to_send_acks()) {
+    received_manager_.ResetAckStates();
+  }
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  // When UpdateReceivedPacketInfo with a time earlier than the time of the
+  // largest observed packet, make sure that the delta is 0, not negative.
+  EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time);
+  EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
+
+  QuicTime four_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(4);
+  ack = received_manager_.GetUpdatedAckFrame(four_ms);
+  if (received_manager_.decide_when_to_send_acks()) {
+    received_manager_.ResetAckStates();
+  }
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  // When UpdateReceivedPacketInfo after not having received a new packet,
+  // the delta should still be accurate.
+  EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
+            ack.ack_frame->ack_delay_time);
+  // And received packet times won't have change.
+  EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
+
+  header.packet_number = QuicPacketNumber(999u);
+  received_manager_.RecordPacketReceived(header, two_ms);
+  header.packet_number = QuicPacketNumber(4u);
+  received_manager_.RecordPacketReceived(header, two_ms);
+  header.packet_number = QuicPacketNumber(1000u);
+  received_manager_.RecordPacketReceived(header, two_ms);
+  EXPECT_TRUE(received_manager_.ack_frame_updated());
+  ack = received_manager_.GetUpdatedAckFrame(two_ms);
+  if (received_manager_.decide_when_to_send_acks()) {
+    received_manager_.ResetAckStates();
+  }
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  // UpdateReceivedPacketInfo should discard any times which can't be
+  // expressed on the wire.
+  EXPECT_EQ(2u, ack.ack_frame->received_packet_times.size());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, UpdateReceivedConnectionStats) {
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  RecordPacketReceipt(1);
+  EXPECT_TRUE(received_manager_.ack_frame_updated());
+  RecordPacketReceipt(6);
+  RecordPacketReceipt(2,
+                      QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1));
+
+  EXPECT_EQ(4u, stats_.max_sequence_reordering);
+  EXPECT_EQ(1000, stats_.max_time_reordering_us);
+  EXPECT_EQ(1u, stats_.packets_reordered);
+}
+
+TEST_P(QuicReceivedPacketManagerTest, LimitAckRanges) {
+  received_manager_.set_max_ack_ranges(10);
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  for (int i = 0; i < 100; ++i) {
+    RecordPacketReceipt(1 + 2 * i);
+    EXPECT_TRUE(received_manager_.ack_frame_updated());
+    received_manager_.GetUpdatedAckFrame(QuicTime::Zero());
+    EXPECT_GE(10u, received_manager_.ack_frame().packets.NumIntervals());
+    EXPECT_EQ(QuicPacketNumber(1u + 2 * i),
+              received_manager_.ack_frame().packets.Max());
+    for (int j = 0; j < std::min(10, i + 1); ++j) {
+      ASSERT_GE(i, j);
+      EXPECT_TRUE(received_manager_.ack_frame().packets.Contains(
+          QuicPacketNumber(1 + (i - j) * 2)));
+      if (i > j) {
+        EXPECT_FALSE(received_manager_.ack_frame().packets.Contains(
+            QuicPacketNumber((i - j) * 2)));
+      }
+    }
+  }
+}
+
+TEST_P(QuicReceivedPacketManagerTest, IgnoreOutOfOrderTimestamps) {
+  EXPECT_FALSE(received_manager_.ack_frame_updated());
+  RecordPacketReceipt(1, QuicTime::Zero());
+  EXPECT_TRUE(received_manager_.ack_frame_updated());
+  EXPECT_EQ(1u, received_manager_.ack_frame().received_packet_times.size());
+  RecordPacketReceipt(2,
+                      QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1));
+  EXPECT_EQ(2u, received_manager_.ack_frame().received_packet_times.size());
+  RecordPacketReceipt(3, QuicTime::Zero());
+  EXPECT_EQ(2u, received_manager_.ack_frame().received_packet_times.size());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, HasMissingPackets) {
+  if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+    EXPECT_QUIC_BUG(received_manager_.PeerFirstSendingPacketNumber(),
+                    "No packets have been received yet");
+  } else {
+    EXPECT_EQ(QuicPacketNumber(1),
+              received_manager_.PeerFirstSendingPacketNumber());
+  }
+  RecordPacketReceipt(4, QuicTime::Zero());
+  if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+    EXPECT_EQ(QuicPacketNumber(4),
+              received_manager_.PeerFirstSendingPacketNumber());
+    EXPECT_FALSE(received_manager_.HasMissingPackets());
+  } else {
+    EXPECT_TRUE(received_manager_.HasMissingPackets());
+    EXPECT_EQ(QuicPacketNumber(1),
+              received_manager_.PeerFirstSendingPacketNumber());
+  }
+  RecordPacketReceipt(3, QuicTime::Zero());
+  if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+    EXPECT_FALSE(received_manager_.HasMissingPackets());
+    EXPECT_EQ(QuicPacketNumber(3),
+              received_manager_.PeerFirstSendingPacketNumber());
+  } else {
+    EXPECT_TRUE(received_manager_.HasMissingPackets());
+    EXPECT_EQ(QuicPacketNumber(1),
+              received_manager_.PeerFirstSendingPacketNumber());
+  }
+  RecordPacketReceipt(1, QuicTime::Zero());
+  EXPECT_EQ(QuicPacketNumber(1),
+            received_manager_.PeerFirstSendingPacketNumber());
+  EXPECT_TRUE(received_manager_.HasMissingPackets());
+  RecordPacketReceipt(2, QuicTime::Zero());
+  EXPECT_EQ(QuicPacketNumber(1),
+            received_manager_.PeerFirstSendingPacketNumber());
+  EXPECT_FALSE(received_manager_.HasMissingPackets());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, OutOfOrderReceiptCausesAckSent) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(3, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 3);
+  if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+    // Delayed ack is scheduled.
+    CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+  } else {
+    // Should ack immediately since we have missing packets.
+    CheckAckTimeout(clock_.ApproximateNow());
+  }
+
+  RecordPacketReceipt(2, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 2);
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 1);
+  // Should ack immediately, since this fills the last hole.
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  RecordPacketReceipt(4, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 4);
+  // Delayed ack is scheduled.
+  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+}
+
+TEST_P(QuicReceivedPacketManagerTest, OutOfOrderAckReceiptCausesNoAck) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(2, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 2);
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 1);
+  EXPECT_FALSE(HasPendingAck());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, AckReceiptCausesAckSend) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 1);
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(2, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 2);
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(3, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 3);
+  // Delayed ack is scheduled.
+  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+  clock_.AdvanceTime(kDelayedAckTime);
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  RecordPacketReceipt(4, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 4);
+  EXPECT_FALSE(HasPendingAck());
+
+  RecordPacketReceipt(5, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(!kInstigateAck, 5);
+  EXPECT_FALSE(HasPendingAck());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, AckSentEveryNthPacket) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  received_manager_.set_ack_frequency_before_ack_decimation(3);
+
+  // Receives packets 1 - 39.
+  for (size_t i = 1; i <= 39; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 3 == 0) {
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+}
+
+TEST_P(QuicReceivedPacketManagerTest, AckDecimationReducesAcks) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_,
+                                            ACK_DECIMATION_WITH_REORDERING);
+
+  // Start ack decimation from 10th packet.
+  received_manager_.set_min_received_before_ack_decimation(10);
+
+  // Receives packets 1 - 29.
+  for (size_t i = 1; i <= 29; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i <= 10) {
+      // For packets 1-10, ack every 2 packets.
+      if (i % 2 == 0) {
+        CheckAckTimeout(clock_.ApproximateNow());
+      } else {
+        CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+      }
+      continue;
+    }
+    // ack at 20.
+    if (i == 20) {
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kMinRttMs * 0.25);
+    }
+  }
+
+  // We now receive the 30th packet, and so we send an ack.
+  RecordPacketReceipt(30, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 30);
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, SendDelayedAfterQuiescence) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetFastAckAfterQuiescence(&received_manager_,
+                                                           true);
+  // The beginning of the connection counts as quiescence.
+  QuicTime ack_time =
+      clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 1);
+  CheckAckTimeout(ack_time);
+  // Simulate delayed ack alarm firing.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // Process another packet immediately after sending the ack and expect the
+  // ack timeout to be set delayed ack time in the future.
+  ack_time = clock_.ApproximateNow() + kDelayedAckTime;
+  RecordPacketReceipt(2, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 2);
+  CheckAckTimeout(ack_time);
+  // Simulate delayed ack alarm firing.
+  clock_.AdvanceTime(kDelayedAckTime);
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // Wait 1 second and enesure the ack timeout is set to 1ms in the future.
+  clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+  ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+  RecordPacketReceipt(3, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 3);
+  CheckAckTimeout(ack_time);
+}
+
+TEST_P(QuicReceivedPacketManagerTest, SendDelayedAckDecimation) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_, ACK_DECIMATION);
+  // The ack time should be based on min_rtt * 1/4, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25;
+
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (uint64_t i = 1; i < 10; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest,
+       SendDelayedAckAckDecimationAfterQuiescence) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_, ACK_DECIMATION);
+  QuicReceivedPacketManagerPeer::SetFastAckAfterQuiescence(&received_manager_,
+                                                           true);
+  // The beginning of the connection counts as quiescence.
+  QuicTime ack_time =
+      clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+  RecordPacketReceipt(1, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 1);
+  CheckAckTimeout(ack_time);
+  // Simulate delayed ack alarm firing.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // Process another packet immedately after sending the ack and expect the
+  // ack timeout to be set delayed ack time in the future.
+  ack_time = clock_.ApproximateNow() + kDelayedAckTime;
+  RecordPacketReceipt(2, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 2);
+  CheckAckTimeout(ack_time);
+  // Simulate delayed ack alarm firing.
+  clock_.AdvanceTime(kDelayedAckTime);
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // Wait 1 second and enesure the ack timeout is set to 1ms in the future.
+  clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+  ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+  RecordPacketReceipt(3, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, 3);
+  CheckAckTimeout(ack_time);
+  // Process enough packets to get into ack decimation behavior.
+  // The ack time should be based on min_rtt/4, since it's less than the
+  // default delayed ack time.
+  ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25;
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 4; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+  EXPECT_FALSE(HasPendingAck());
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (uint64_t i = 1; i < 10; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // Wait 1 second and enesure the ack timeout is set to 1ms in the future.
+  clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
+  ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
+  RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10);
+  CheckAckTimeout(ack_time);
+}
+
+TEST_P(QuicReceivedPacketManagerTest,
+       SendDelayedAckDecimationUnlimitedAggregation) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicConfig config;
+  QuicTagVector connection_options;
+  connection_options.push_back(kACKD);
+  // No limit on the number of packets received before sending an ack.
+  connection_options.push_back(kAKDU);
+  config.SetConnectionOptionsToSend(connection_options);
+  received_manager_.SetFromConfig(config, Perspective::IS_CLIENT);
+
+  // The ack time should be based on min_rtt/4, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25;
+
+  // Process all the initial packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  // 18 packets will not cause an ack to be sent.  19 will because when
+  // stop waiting frames are in use, we ack every 20 packets no matter what.
+  for (int i = 1; i <= 18; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(ack_time);
+}
+
+TEST_P(QuicReceivedPacketManagerTest, SendDelayedAckDecimationEighthRtt) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_, ACK_DECIMATION);
+  QuicReceivedPacketManagerPeer::SetAckDecimationDelay(&received_manager_,
+                                                       0.125);
+
+  // The ack time should be based on min_rtt/8, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125;
+
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (uint64_t i = 1; i < 10; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest, SendDelayedAckDecimationWithReordering) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_,
+                                            ACK_DECIMATION_WITH_REORDERING);
+
+  // The ack time should be based on min_rtt/4, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25;
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  // Receive one packet out of order and then the rest in order.
+  // The loop leaves a one packet gap between acks sent to simulate some loss.
+  for (int j = 0; j < 3; ++j) {
+    // Process packet 10 first and ensure the timeout is one eighth min_rtt.
+    RecordPacketReceipt(kFirstDecimatedPacket + 9 + (j * 11),
+                        clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 9 + (j * 11));
+    ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
+    CheckAckTimeout(ack_time);
+
+    // The 10th received packet causes an ack to be sent.
+    for (int i = 0; i < 9; ++i) {
+      RecordPacketReceipt(kFirstDecimatedPacket + i + (j * 11),
+                          clock_.ApproximateNow());
+      MaybeUpdateAckTimeout(kInstigateAck,
+                            kFirstDecimatedPacket + i + (j * 11));
+    }
+    CheckAckTimeout(clock_.ApproximateNow());
+  }
+}
+
+TEST_P(QuicReceivedPacketManagerTest,
+       SendDelayedAckDecimationWithLargeReordering) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_,
+                                            ACK_DECIMATION_WITH_REORDERING);
+  // The ack time should be based on min_rtt/4, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.25;
+
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  RecordPacketReceipt(kFirstDecimatedPacket + 19, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 19);
+  ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125;
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (int i = 1; i < 9; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // The next packet received in order will cause an immediate ack, because it
+  // fills a hole.
+  RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10);
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest,
+       SendDelayedAckDecimationWithReorderingEighthRtt) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_,
+                                            ACK_DECIMATION_WITH_REORDERING);
+  QuicReceivedPacketManagerPeer::SetAckDecimationDelay(&received_manager_,
+                                                       0.125);
+  // The ack time should be based on min_rtt/8, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125;
+
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  // Process packet 10 first and ensure the timeout is one eighth min_rtt.
+  RecordPacketReceipt(kFirstDecimatedPacket + 9, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 9);
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (int i = 1; i < 9; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck + i, kFirstDecimatedPacket);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+TEST_P(QuicReceivedPacketManagerTest,
+       SendDelayedAckDecimationWithLargeReorderingEighthRtt) {
+  if (!received_manager_.decide_when_to_send_acks()) {
+    return;
+  }
+  EXPECT_FALSE(HasPendingAck());
+  QuicReceivedPacketManagerPeer::SetAckMode(&received_manager_,
+                                            ACK_DECIMATION_WITH_REORDERING);
+  QuicReceivedPacketManagerPeer::SetAckDecimationDelay(&received_manager_,
+                                                       0.125);
+
+  // The ack time should be based on min_rtt/8, since it's less than the
+  // default delayed ack time.
+  QuicTime ack_time = clock_.ApproximateNow() + kMinRttMs * 0.125;
+  // Process all the packets in order so there aren't missing packets.
+  uint64_t kFirstDecimatedPacket = 101;
+  for (uint64_t i = 1; i < kFirstDecimatedPacket; ++i) {
+    RecordPacketReceipt(i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, i);
+    if (i % 2 == 0) {
+      // Ack every 2 packets by default.
+      CheckAckTimeout(clock_.ApproximateNow());
+    } else {
+      CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+    }
+  }
+
+  RecordPacketReceipt(kFirstDecimatedPacket, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket);
+  CheckAckTimeout(ack_time);
+
+  RecordPacketReceipt(kFirstDecimatedPacket + 19, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 19);
+  CheckAckTimeout(ack_time);
+
+  // The 10th received packet causes an ack to be sent.
+  for (int i = 1; i < 9; ++i) {
+    RecordPacketReceipt(kFirstDecimatedPacket + i, clock_.ApproximateNow());
+    MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + i);
+  }
+  CheckAckTimeout(clock_.ApproximateNow());
+
+  // The next packet received in order will cause an immediate ack, because it
+  // fills a hole.
+  RecordPacketReceipt(kFirstDecimatedPacket + 10, clock_.ApproximateNow());
+  MaybeUpdateAckTimeout(kInstigateAck, kFirstDecimatedPacket + 10);
+  CheckAckTimeout(clock_.ApproximateNow());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace quic