blob: 8a4d7bd0dcad8df4acbb77c2462569f6fb694e22 [file] [log] [blame]
// Copyright (c) 2012 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 "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/congestion_control/quic_receipt_metrics_collector.h"
#include "net/quic/congestion_control/quic_send_scheduler.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/quic_protocol.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace testing {
class QuicSendSchedulerTest : public ::testing::Test {
protected:
void SetUpCongestionType(CongestionFeedbackType congestion_type) {
sender_.reset(new QuicSendScheduler(&clock_, congestion_type));
}
MockClock clock_;
scoped_ptr<QuicSendScheduler> sender_;
};
TEST_F(QuicSendSchedulerTest, FixedRateSenderAPI) {
SetUpCongestionType(kFixRate);
QuicCongestionFeedbackFrame congestion_feedback;
congestion_feedback.type = kFixRate;
congestion_feedback.fix_rate.bitrate_in_bytes_per_second = 30000;
sender_->OnIncomingQuicCongestionFeedbackFrame(congestion_feedback);
EXPECT_EQ(-1, sender_->PeakSustainedBandwidth());
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(1, kMaxPacketSize, false);
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(40),
sender_->TimeUntilSend(false));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(35));
EXPECT_EQ(QuicTime::Delta::Infinite(),
sender_->TimeUntilSend(false));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_EQ(QuicTime::Delta::Infinite(),
sender_->TimeUntilSend(false));
}
TEST_F(QuicSendSchedulerTest, FixedRatePacing) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
ack.received_info.largest_received = 0;
sender_->OnIncomingAckFrame(ack);
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
feedback.fix_rate.bitrate_in_bytes_per_second = 100000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
QuicTime acc_advance_time;
for (int i = 1; i <= 100; ++i) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i, kMaxPacketSize, false);
QuicTime::Delta advance_time = sender_->TimeUntilSend(false);
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packet we sent.
ack.received_info.RecordReceived(i);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(QuicTime::FromMilliseconds(1200), acc_advance_time);
}
TEST_F(QuicSendSchedulerTest, AvailableCongestionWindow) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
sender_->OnIncomingAckFrame(ack);
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
feedback.fix_rate.bitrate_in_bytes_per_second = 100000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
const int32 num_packets = 12;
for (int i = 1; i <= num_packets; i++) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
sender_->SentPacket(i, 100, false);
EXPECT_EQ(kMaxPacketSize - (i * 100), sender_->AvailableCongestionWindow());
}
// Ack the packets we sent.
for (int i = 1; i <= num_packets; i++) {
ack.received_info.RecordReceived(i);
}
sender_->OnIncomingAckFrame(ack);
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
}
TEST_F(QuicSendSchedulerTest, FixedRateBandwidth) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
sender_->OnIncomingAckFrame(ack);
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
feedback.fix_rate.bitrate_in_bytes_per_second = 100000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
for (int i = 1; i <= 100; ++i) {
QuicTime::Delta advance_time = sender_->TimeUntilSend(false);
clock_.AdvanceTime(advance_time);
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i, 1000, false);
// Ack the packet we sent.
ack.received_info.RecordReceived(i);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
EXPECT_EQ(101010, sender_->PeakSustainedBandwidth());
EXPECT_EQ(101010, sender_->SentBandwidth());
}
TEST_F(QuicSendSchedulerTest, BandwidthWith3SecondGap) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
sender_->OnIncomingAckFrame(ack);
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
feedback.fix_rate.bitrate_in_bytes_per_second = 100000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
for (int i = 1; i <= 100; ++i) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i, 1000, false);
// Ack the packet we sent.
ack.received_info.RecordReceived(i);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
EXPECT_EQ(100000, sender_->SentBandwidth());
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
EXPECT_EQ(50000, sender_->SentBandwidth());
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2100));
EXPECT_EQ(100000, sender_->BandwidthEstimate());
EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
EXPECT_EQ(0, sender_->SentBandwidth());
for (int i = 1; i <= 150; ++i) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize, sender_->AvailableCongestionWindow());
sender_->SentPacket(i + 100, 1000, false);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
// Ack the packet we sent.
ack.received_info.RecordReceived(i + 100);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(100000, sender_->BandwidthEstimate());
EXPECT_EQ(100000, sender_->PeakSustainedBandwidth());
EXPECT_EQ(50000, sender_->SentBandwidth());
}
TEST_F(QuicSendSchedulerTest, Pacing) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
ack.received_info.largest_received = 0;
sender_->OnIncomingAckFrame(ack);
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
// Test a high bitrate (8Mbit/s) to trigger pacing.
feedback.fix_rate.bitrate_in_bytes_per_second = 1000000;
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback);
QuicTime acc_advance_time;
for (int i = 1; i <= 100;) {
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
EXPECT_EQ(kMaxPacketSize * 2, sender_->AvailableCongestionWindow());
sender_->SentPacket(i++, kMaxPacketSize, false);
EXPECT_TRUE(sender_->TimeUntilSend(false).IsZero());
sender_->SentPacket(i++, kMaxPacketSize, false);
QuicTime::Delta advance_time = sender_->TimeUntilSend(false);
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packets we sent.
ack.received_info.RecordReceived(i - 2);
sender_->OnIncomingAckFrame(ack);
ack.received_info.RecordReceived(i - 1);
sender_->OnIncomingAckFrame(ack);
}
EXPECT_EQ(QuicTime::FromMilliseconds(120), acc_advance_time);
}
} // namespace testing
} // namespace net