blob: 0be0b0aac017466ee522ff1e3b71d7766d08d028 [file] [log] [blame]
// 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/quic/congestion_control/pacing_sender.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Return;
using testing::StrictMock;
using testing::_;
namespace net {
namespace test {
const QuicByteCount kBytesInFlight = 1024;
const int kInitialBurstPackets = 10;
class PacingSenderTest : public ::testing::Test {
protected:
PacingSenderTest()
: zero_time_(QuicTime::Delta::Zero()),
infinite_time_(QuicTime::Delta::Infinite()),
sequence_number_(1),
mock_sender_(new StrictMock<MockSendAlgorithm>()),
pacing_sender_(new PacingSender(mock_sender_,
QuicTime::Delta::FromMilliseconds(1),
0)) {
// Pick arbitrary time.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(9));
}
virtual ~PacingSenderTest() {}
void CheckPacketIsSentImmediately() {
// 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_, TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(zero_time_));
// Verify that the packet can be sent immediately.
EXPECT_EQ(zero_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA));
}
// Actually send the packet.
EXPECT_CALL(*mock_sender_,
OnPacketSent(clock_.Now(), kBytesInFlight, sequence_number_,
kMaxPacketSize, HAS_RETRANSMITTABLE_DATA));
pacing_sender_->OnPacketSent(clock_.Now(), kBytesInFlight,
sequence_number_++, kMaxPacketSize,
HAS_RETRANSMITTABLE_DATA);
}
void CheckAckIsSentImmediately() {
// In order for the ack to be sendable, the underlying sender must
// permit it to be sent immediately.
EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
0,
NO_RETRANSMITTABLE_DATA))
.WillOnce(Return(zero_time_));
// Verify that the ACK can be sent immediately.
EXPECT_EQ(zero_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
0,
NO_RETRANSMITTABLE_DATA));
// Actually send the packet.
EXPECT_CALL(*mock_sender_,
OnPacketSent(clock_.Now(), 0, sequence_number_,
kMaxPacketSize, NO_RETRANSMITTABLE_DATA));
pacing_sender_->OnPacketSent(clock_.Now(), 0,
sequence_number_++, kMaxPacketSize,
NO_RETRANSMITTABLE_DATA);
}
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_, TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(zero_time_));
// Verify that the packet is delayed.
EXPECT_EQ(delay.ToMicroseconds(),
pacing_sender_->TimeUntilSend(
clock_.Now(), kBytesInFlight,
HAS_RETRANSMITTABLE_DATA).ToMicroseconds());
}
}
const QuicTime::Delta zero_time_;
const QuicTime::Delta infinite_time_;
MockClock clock_;
QuicPacketSequenceNumber sequence_number_;
StrictMock<MockSendAlgorithm>* mock_sender_;
scoped_ptr<PacingSender> pacing_sender_;
};
TEST_F(PacingSenderTest, NoSend) {
for (int i = 0; i < 2; ++i) {
EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(infinite_time_));
EXPECT_EQ(infinite_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA));
}
}
TEST_F(PacingSenderTest, SendNow) {
for (int i = 0; i < 2; ++i) {
EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA))
.WillOnce(Return(zero_time_));
EXPECT_EQ(zero_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
kBytesInFlight,
HAS_RETRANSMITTABLE_DATA));
}
}
TEST_F(PacingSenderTest, VariousSending) {
// Configure pacing rate of 1 packet per 1 ms.
EXPECT_CALL(*mock_sender_, PacingRate())
.WillRepeatedly(Return(QuicBandwidth::FromBytesAndTimeDelta(
kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1))));
// Now update the RTT and verify that packets are actually paced.
EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kBytesInFlight, _, _));
SendAlgorithmInterface::CongestionVector empty_map;
pacing_sender_->OnCongestionEvent(true, kBytesInFlight, empty_map, empty_map);
CheckPacketIsSentImmediately();
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));
CheckAckIsSentImmediately();
// 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();
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
// Wake up too early.
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();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
TEST_F(PacingSenderTest, CongestionAvoidanceSending) {
// Configure pacing rate of 1 packet per 1 ms.
EXPECT_CALL(*mock_sender_, PacingRate())
.WillRepeatedly(Return(QuicBandwidth::FromBytesAndTimeDelta(
kMaxPacketSize * 1.25, QuicTime::Delta::FromMilliseconds(2))));
// Now update the RTT and verify that packets are actually paced.
EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kBytesInFlight, _, _));
SendAlgorithmInterface::CongestionVector empty_map;
pacing_sender_->OnCongestionEvent(true, kBytesInFlight, empty_map, empty_map);
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
// The first packet was a "make up", then we sent two packets "into the
// future", so the delay should be 2200us.
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2200));
// Wake up on time.
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(2200));
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(1600));
CheckAckIsSentImmediately();
// Wake up late.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(4));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2400));
// Wake up really late.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2400));
// Wake up really late again, but application pause partway through.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2200));
// Wake up too early.
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2200));
// Wake up early, but after enough time has passed to permit a send.
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1200));
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMicroseconds(2600));
}
TEST_F(PacingSenderTest, InitialBurst) {
pacing_sender_.reset();
mock_sender_ = new StrictMock<MockSendAlgorithm>();
pacing_sender_.reset(new PacingSender(mock_sender_,
QuicTime::Delta::FromMilliseconds(1),
10));
// Configure pacing rate of 1 packet per 1 ms.
EXPECT_CALL(*mock_sender_, PacingRate())
.WillRepeatedly(Return(QuicBandwidth::FromBytesAndTimeDelta(
kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1))));
// Update the RTT and verify that the first 10 packets aren't paced.
EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kBytesInFlight, _, _));
SendAlgorithmInterface::CongestionVector empty_map;
pacing_sender_->OnCongestionEvent(true, kBytesInFlight, empty_map, empty_map);
// 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();
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.
EXPECT_CALL(*mock_sender_,
TimeUntilSend(clock_.Now(),
0,
HAS_RETRANSMITTABLE_DATA)).
WillOnce(Return(zero_time_));
EXPECT_EQ(zero_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
0,
HAS_RETRANSMITTABLE_DATA));
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();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
TEST_F(PacingSenderTest, InitialBurstNoRttMeasurement) {
pacing_sender_.reset();
mock_sender_ = new StrictMock<MockSendAlgorithm>();
pacing_sender_.reset(new PacingSender(mock_sender_,
QuicTime::Delta::FromMilliseconds(1),
10));
// Configure pacing rate of 1 packet per 1 ms.
EXPECT_CALL(*mock_sender_, PacingRate())
.WillRepeatedly(Return(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();
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.
EXPECT_CALL(*mock_sender_,
TimeUntilSend(clock_.Now(),
0,
HAS_RETRANSMITTABLE_DATA)).
WillOnce(Return(zero_time_));
EXPECT_EQ(zero_time_,
pacing_sender_->TimeUntilSend(clock_.Now(),
0,
HAS_RETRANSMITTABLE_DATA));
// 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();
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
} // namespace test
} // namespace net