Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/congestion_control/pacing_sender_test.cc b/quic/core/congestion_control/pacing_sender_test.cc
new file mode 100644
index 0000000..0bb9258
--- /dev/null
+++ b/quic/core/congestion_control/pacing_sender_test.cc
@@ -0,0 +1,432 @@
+// Copyright (c) 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/congestion_control/pacing_sender.h"
+
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.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"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+using testing::_;
+using testing::AtMost;
+using testing::IsEmpty;
+using testing::Return;
+using testing::StrictMock;
+
+namespace quic {
+namespace test {
+
+const QuicByteCount kBytesInFlight = 1024;
+const int kInitialBurstPackets = 10;
+
+class PacingSenderTest : public QuicTest {
+ protected:
+  PacingSenderTest()
+      : zero_time_(QuicTime::Delta::Zero()),
+        infinite_time_(QuicTime::Delta::Infinite()),
+        packet_number_(1),
+        mock_sender_(new StrictMock<MockSendAlgorithm>()),
+        pacing_sender_(new PacingSender) {
+    pacing_sender_->set_sender(mock_sender_.get());
+    // Pick arbitrary time.
+    clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(9));
+  }
+
+  ~PacingSenderTest() override {}
+
+  void InitPacingRate(QuicPacketCount burst_size, QuicBandwidth bandwidth) {
+    mock_sender_ = QuicMakeUnique<StrictMock<MockSendAlgorithm>>();
+    pacing_sender_ = QuicMakeUnique<PacingSender>();
+    pacing_sender_->set_sender(mock_sender_.get());
+    EXPECT_CALL(*mock_sender_, PacingRate(_)).WillRepeatedly(Return(bandwidth));
+    if (burst_size == 0) {
+      EXPECT_CALL(*mock_sender_, OnCongestionEvent(_, _, _, _, _));
+      LostPacketVector lost_packets;
+      lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
+      AckedPacketVector empty;
+      pacing_sender_->OnCongestionEvent(true, 1234, clock_.Now(), empty,
+                                        lost_packets);
+    } else if (burst_size != kInitialBurstPackets) {
+      QUIC_LOG(FATAL) << "Unsupported burst_size " << burst_size
+                      << " specificied, only 0 and " << kInitialBurstPackets
+                      << " are supported.";
+    }
+  }
+
+  void CheckPacketIsSentImmediately(HasRetransmittableData retransmittable_data,
+                                    QuicByteCount bytes_in_flight,
+                                    bool in_recovery,
+                                    bool cwnd_limited,
+                                    QuicPacketCount cwnd) {
+    // In order for the packet to be sendable, the underlying sender must
+    // permit it to be sent immediately.
+    for (int i = 0; i < 2; ++i) {
+      EXPECT_CALL(*mock_sender_, CanSend(bytes_in_flight))
+          .WillOnce(Return(true));
+      // Verify that the packet can be sent immediately.
+      EXPECT_EQ(zero_time_,
+                pacing_sender_->TimeUntilSend(clock_.Now(), bytes_in_flight));
+    }
+
+    // Actually send the packet.
+    if (bytes_in_flight == 0) {
+      EXPECT_CALL(*mock_sender_, InRecovery()).WillOnce(Return(in_recovery));
+    }
+    EXPECT_CALL(*mock_sender_,
+                OnPacketSent(clock_.Now(), bytes_in_flight, packet_number_,
+                             kMaxPacketSize, retransmittable_data));
+    EXPECT_CALL(*mock_sender_, GetCongestionWindow())
+        .Times(AtMost(1))
+        .WillRepeatedly(Return(cwnd * kDefaultTCPMSS));
+    EXPECT_CALL(*mock_sender_, CanSend(bytes_in_flight + kMaxPacketSize))
+        .Times(AtMost(1))
+        .WillRepeatedly(Return(!cwnd_limited));
+    pacing_sender_->OnPacketSent(clock_.Now(), bytes_in_flight,
+                                 packet_number_++, kMaxPacketSize,
+                                 retransmittable_data);
+  }
+
+  void CheckPacketIsSentImmediately() {
+    CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight,
+                                 false, false, 10);
+  }
+
+  void CheckPacketIsDelayed(QuicTime::Delta delay) {
+    // In order for the packet to be sendable, the underlying sender must
+    // permit it to be sent immediately.
+    for (int i = 0; i < 2; ++i) {
+      EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight))
+          .WillOnce(Return(true));
+      // Verify that the packet is delayed.
+      EXPECT_EQ(delay.ToMicroseconds(),
+                pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight)
+                    .ToMicroseconds());
+    }
+  }
+
+  void UpdateRtt() {
+    EXPECT_CALL(*mock_sender_,
+                OnCongestionEvent(true, kBytesInFlight, _, _, _));
+    AckedPacketVector empty_acked;
+    LostPacketVector empty_lost;
+    pacing_sender_->OnCongestionEvent(true, kBytesInFlight, clock_.Now(),
+                                      empty_acked, empty_lost);
+  }
+
+  void OnApplicationLimited() { pacing_sender_->OnApplicationLimited(); }
+
+  const QuicTime::Delta zero_time_;
+  const QuicTime::Delta infinite_time_;
+  MockClock clock_;
+  QuicPacketNumber packet_number_;
+  std::unique_ptr<StrictMock<MockSendAlgorithm>> mock_sender_;
+  std::unique_ptr<PacingSender> pacing_sender_;
+};
+
+TEST_F(PacingSenderTest, NoSend) {
+  for (int i = 0; i < 2; ++i) {
+    EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight)).WillOnce(Return(false));
+    EXPECT_EQ(infinite_time_,
+              pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
+  }
+}
+
+TEST_F(PacingSenderTest, SendNow) {
+  for (int i = 0; i < 2; ++i) {
+    EXPECT_CALL(*mock_sender_, CanSend(kBytesInFlight)).WillOnce(Return(true));
+    EXPECT_EQ(zero_time_,
+              pacing_sender_->TimeUntilSend(clock_.Now(), kBytesInFlight));
+  }
+}
+
+TEST_F(PacingSenderTest, VariousSending) {
+  // Configure pacing rate of 1 packet per 1 ms, no initial burst.
+  InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta(
+                        kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+
+  // Now update the RTT and verify that packets are actually paced.
+  UpdateRtt();
+
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 2.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up on time.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up late.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(4));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up really late.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up really late again, but application pause partway through.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  OnApplicationLimited();
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+  // Wake up early, but after enough time has passed to permit a send.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+  CheckPacketIsSentImmediately();
+}
+
+TEST_F(PacingSenderTest, InitialBurst) {
+  // Configure pacing rate of 1 packet per 1 ms.
+  InitPacingRate(10, QuicBandwidth::FromBytesAndTimeDelta(
+                         kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+
+  // Update the RTT and verify that the first 10 packets aren't paced.
+  UpdateRtt();
+
+  // Send 10 packets, and verify that they are not paced.
+  for (int i = 0; i < kInitialBurstPackets; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 2ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+  CheckPacketIsSentImmediately();
+
+  // Next time TimeUntilSend is called with no bytes in flight, pacing should
+  // allow a packet to be sent, and when it's sent, the tokens are refilled.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+  for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 2ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+TEST_F(PacingSenderTest, InitialBurstNoRttMeasurement) {
+  // Configure pacing rate of 1 packet per 1 ms.
+  InitPacingRate(10, QuicBandwidth::FromBytesAndTimeDelta(
+                         kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+
+  // Send 10 packets, and verify that they are not paced.
+  for (int i = 0; i < kInitialBurstPackets; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 2ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+  CheckPacketIsSentImmediately();
+
+  // Next time TimeUntilSend is called with no bytes in flight, the tokens
+  // should be refilled and there should be no delay.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+  // Send 10 packets, and verify that they are not paced.
+  for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 2ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+TEST_F(PacingSenderTest, FastSending) {
+  // Ensure the pacing sender paces, even when the inter-packet spacing is less
+  // than the pacing granularity.
+  InitPacingRate(10,
+                 QuicBandwidth::FromBytesAndTimeDelta(
+                     2 * kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+  // Update the RTT and verify that the first 10 packets aren't paced.
+  UpdateRtt();
+
+  // Send 10 packets, and verify that they are not paced.
+  for (int i = 0; i < kInitialBurstPackets; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", since it's 2 packets/ms, so the delay should be 1.5ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(1500));
+
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+  CheckPacketIsSentImmediately();
+
+  // Next time TimeUntilSend is called with no bytes in flight, the tokens
+  // should be refilled and there should be no delay.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+  for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  // The first packet was a "make up", then we sent two packets "into the
+  // future", so the delay should be 1.5ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(1500));
+}
+
+TEST_F(PacingSenderTest, NoBurstEnteringRecovery) {
+  // Configure pacing rate of 1 packet per 1 ms with no burst tokens.
+  InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta(
+                        kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+  // Sending a packet will set burst tokens.
+  CheckPacketIsSentImmediately();
+
+  // Losing a packet will set clear burst tokens.
+  LostPacketVector lost_packets;
+  lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
+  AckedPacketVector empty_acked;
+  EXPECT_CALL(*mock_sender_,
+              OnCongestionEvent(true, kMaxPacketSize, _, IsEmpty(), _));
+  pacing_sender_->OnCongestionEvent(true, kMaxPacketSize, clock_.Now(),
+                                    empty_acked, lost_packets);
+  // One packet is sent immediately, because of 1ms pacing granularity.
+  CheckPacketIsSentImmediately();
+  // Ensure packets are immediately paced.
+  EXPECT_CALL(*mock_sender_, CanSend(kDefaultTCPMSS)).WillOnce(Return(true));
+  // Verify the next packet is paced and delayed 2ms due to granularity.
+  EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
+            pacing_sender_->TimeUntilSend(clock_.Now(), kDefaultTCPMSS));
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+TEST_F(PacingSenderTest, NoBurstInRecovery) {
+  // Configure pacing rate of 1 packet per 1 ms with no burst tokens.
+  InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta(
+                        kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+
+  UpdateRtt();
+
+  // Ensure only one packet is sent immediately and the rest are paced.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, true, false, 10);
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+TEST_F(PacingSenderTest, CwndLimited) {
+  // Configure pacing rate of 1 packet per 1 ms, no initial burst.
+  InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta(
+                        kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+
+  UpdateRtt();
+
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  // Packet 3 will be delayed 2ms.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+  // Wake up on time.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
+  // After sending packet 3, cwnd is limited.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
+                               true, 10);
+
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+  // Verify pacing sender stops making up for lost time after sending packet 3.
+  // Packet 6 will be delayed 2ms.
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+TEST_F(PacingSenderTest, LumpyPacingWithInitialBurstToken) {
+  // Set lumpy size to be 3, and cwnd faction to 0.5
+  SetQuicFlag(&FLAGS_quic_lumpy_pacing_size, 3);
+  SetQuicFlag(&FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
+  // Configure pacing rate of 1 packet per 1 ms.
+  InitPacingRate(10, QuicBandwidth::FromBytesAndTimeDelta(
+                         kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
+  UpdateRtt();
+
+  // Send 10 packets, and verify that they are not paced.
+  for (int i = 0; i < kInitialBurstPackets; ++i) {
+    CheckPacketIsSentImmediately();
+  }
+
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  // Packet 14 will be delayed 3ms.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(3));
+
+  // Wake up on time.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  // Packet 17 will be delayed 3ms.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(3));
+
+  // Application throttles sending.
+  OnApplicationLimited();
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  CheckPacketIsSentImmediately();
+  // Packet 20 will be delayed 3ms.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(3));
+
+  // Wake up on time.
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3));
+  CheckPacketIsSentImmediately();
+  // After sending packet 21, cwnd is limited.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
+                               true, 10);
+
+  clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+  // Suppose cwnd size is 5, so that lumpy size becomes 2.
+  CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
+                               false, 5);
+  CheckPacketIsSentImmediately();
+  // Packet 24 will be delayed 2ms.
+  CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+}  // namespace test
+}  // namespace quic