blob: 457538f4552ee8d0697065e76cbdc83ca23b26c6 [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.
// Test of the full congestion control chain.
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
using std::max;
namespace net {
namespace test {
class QuicCongestionManagerPeer : public QuicCongestionManager {
public:
explicit QuicCongestionManagerPeer(const QuicClock* clock,
CongestionFeedbackType congestion_type)
: QuicCongestionManager(clock, congestion_type) {
}
using QuicCongestionManager::BandwidthEstimate;
};
class QuicCongestionControlTest : public ::testing::Test {
protected:
QuicCongestionControlTest()
: start_(clock_.ApproximateNow()) {
}
void SetUpCongestionType(CongestionFeedbackType congestion_type) {
manager_.reset(new QuicCongestionManagerPeer(&clock_, congestion_type));
}
MockClock clock_;
QuicTime start_;
scoped_ptr<QuicCongestionManagerPeer> manager_;
};
TEST_F(QuicCongestionControlTest, FixedRateSenderAPI) {
SetUpCongestionType(kFixRate);
QuicCongestionFeedbackFrame congestion_feedback;
congestion_feedback.type = kFixRate;
congestion_feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(30);
manager_->OnIncomingQuicCongestionFeedbackFrame(congestion_feedback,
clock_.Now());
EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
manager_->SentPacket(1, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(40),
manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(35));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_EQ(QuicTime::Delta::Infinite(),
manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
}
TEST_F(QuicCongestionControlTest, FixedRatePacing) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
ack.received_info.largest_observed = 0;
manager_->OnIncomingAckFrame(ack, clock_.Now());
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(100);
manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
QuicTime acc_advance_time(QuicTime::Zero());
for (QuicPacketSequenceNumber i = 1; i <= 100; ++i) {
EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
manager_->SentPacket(i, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
QuicTime::Delta advance_time = manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packet we sent.
ack.received_info.largest_observed = max(
i, ack.received_info.largest_observed);
manager_->OnIncomingAckFrame(ack, clock_.Now());
}
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1200),
acc_advance_time.Subtract(start_));
}
TEST_F(QuicCongestionControlTest, Pacing) {
SetUpCongestionType(kFixRate);
QuicAckFrame ack;
ack.received_info.largest_observed = 0;
manager_->OnIncomingAckFrame(ack, clock_.Now());
QuicCongestionFeedbackFrame feedback;
feedback.type = kFixRate;
// Test a high bitrate (8Mbit/s) to trigger pacing.
feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(1000);
manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
QuicTime acc_advance_time(QuicTime::Zero());
for (QuicPacketSequenceNumber i = 1; i <= 100;) {
EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
manager_->SentPacket(i++, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
manager_->SentPacket(i++, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
QuicTime::Delta advance_time = manager_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
clock_.AdvanceTime(advance_time);
acc_advance_time = acc_advance_time.Add(advance_time);
// Ack the packets we sent.
ack.received_info.largest_observed = max(
i - 2, ack.received_info.largest_observed);
manager_->OnIncomingAckFrame(ack, clock_.Now());
ack.received_info.largest_observed = max(
i - 1, ack.received_info.largest_observed);
manager_->OnIncomingAckFrame(ack, clock_.Now());
}
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(120),
acc_advance_time.Subtract(start_));
}
// TODO(pwestin): add TCP tests.
// TODO(pwestin): add InterArrival tests.
} // namespace test
} // namespace net