diff options
Diffstat (limited to 'chromium/net/quic/congestion_control/inter_arrival_sender_test.cc')
-rw-r--r-- | chromium/net/quic/congestion_control/inter_arrival_sender_test.cc | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc b/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc new file mode 100644 index 00000000000..d0faca0f8f1 --- /dev/null +++ b/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc @@ -0,0 +1,565 @@ +// 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 "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "net/quic/congestion_control/inter_arrival_sender.h" +#include "net/quic/test_tools/mock_clock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace test { + +class InterArrivalSenderTest : public ::testing::Test { + protected: + InterArrivalSenderTest() + : rtt_(QuicTime::Delta::FromMilliseconds(60)), + one_ms_(QuicTime::Delta::FromMilliseconds(1)), + one_s_(QuicTime::Delta::FromMilliseconds(1000)), + nine_ms_(QuicTime::Delta::FromMilliseconds(9)), + send_start_time_(send_clock_.Now()), + sender_(&send_clock_), + sequence_number_(1), + acked_sequence_number_(1), + feedback_sequence_number_(1) { + send_clock_.AdvanceTime(one_ms_); + receive_clock_.AdvanceTime(one_ms_); + } + + virtual ~InterArrivalSenderTest() { + STLDeleteValues(&sent_packets_); + } + + void SendAvailableCongestionWindow() { + while (sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()) { + QuicByteCount bytes_in_packet = kMaxPacketSize; + sent_packets_[sequence_number_] = + new class SendAlgorithmInterface::SentPacket( + bytes_in_packet, send_clock_.Now()); + + sender_.SentPacket(send_clock_.Now(), sequence_number_, bytes_in_packet, + NOT_RETRANSMISSION); + sequence_number_++; + } + EXPECT_FALSE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + + void AckNPackets(int n) { + for (int i = 0; i < n; ++i) { + sender_.OnIncomingAck(acked_sequence_number_++, kMaxPacketSize, rtt_); + } + } + + void SendDelaySpikeFeedbackMessage(QuicTime::Delta spike_time) { + QuicCongestionFeedbackFrame feedback; + feedback.type = kInterArrival; + feedback.inter_arrival.accumulated_number_of_lost_packets = 0; + receive_clock_.AdvanceTime(spike_time); + QuicTime receive_time = receive_clock_.ApproximateNow(); + feedback.inter_arrival.received_packet_times.insert( + std::pair<QuicPacketSequenceNumber, QuicTime>( + feedback_sequence_number_, receive_time)); + feedback_sequence_number_++; + + // We need to send feedback for 2 packets since they where sent at the + // same time. + feedback.inter_arrival.received_packet_times.insert( + std::pair<QuicPacketSequenceNumber, QuicTime>( + feedback_sequence_number_, receive_time)); + feedback_sequence_number_++; + + sender_.OnIncomingQuicCongestionFeedbackFrame(feedback, send_clock_.Now(), + sent_packets_); + } + + void SendFeedbackMessageNPackets(int n, + QuicTime::Delta delta_odd, + QuicTime::Delta delta_even) { + QuicCongestionFeedbackFrame feedback; + feedback.type = kInterArrival; + feedback.inter_arrival.accumulated_number_of_lost_packets = 0; + for (int i = 0; i < n; ++i) { + if (feedback_sequence_number_ % 2) { + receive_clock_.AdvanceTime(delta_even); + } else { + receive_clock_.AdvanceTime(delta_odd); + } + QuicTime receive_time = receive_clock_.ApproximateNow(); + feedback.inter_arrival.received_packet_times.insert( + std::pair<QuicPacketSequenceNumber, QuicTime>( + feedback_sequence_number_, receive_time)); + feedback_sequence_number_++; + } + sender_.OnIncomingQuicCongestionFeedbackFrame(feedback, send_clock_.Now(), + sent_packets_); + } + + QuicTime::Delta SenderDeltaSinceStart() { + return send_clock_.ApproximateNow().Subtract(send_start_time_); + } + + const QuicTime::Delta rtt_; + const QuicTime::Delta one_ms_; + const QuicTime::Delta one_s_; + const QuicTime::Delta nine_ms_; + MockClock send_clock_; + MockClock receive_clock_; + const QuicTime send_start_time_; + InterArrivalSender sender_; + QuicPacketSequenceNumber sequence_number_; + QuicPacketSequenceNumber acked_sequence_number_; + QuicPacketSequenceNumber feedback_sequence_number_; + SendAlgorithmInterface::SentPacketsMap sent_packets_; +}; + +TEST_F(InterArrivalSenderTest, ProbeFollowedByFullRampUpCycle) { + QuicCongestionFeedbackFrame feedback; + // At startup make sure we can send. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // Send 5 bursts. + for (int i = 0; i < 4; ++i) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + SendAvailableCongestionWindow(); + + // We have now sent our probe. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), NOT_RETRANSMISSION, + HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsInfinite()); + + AckNPackets(10); + SendFeedbackMessageNPackets(10, one_ms_, nine_ms_); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // We should now have our probe rate. + QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41); + int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond / + acc_arrival_time.ToMicroseconds(); + EXPECT_NEAR(0.7f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + DLOG(INFO) << "After probe"; + // Send 50 bursts, make sure that we move fast in the beginning. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.875f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 600, 10); + + // Send 50 bursts, make sure that we slow down towards the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.95f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 1100, 10); + + // Send 50 bursts, make sure that we move very slow close to the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.99f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 1560, 10); + DLOG(INFO) << "Near available channel estimate"; + + // Send 50 bursts, make sure that we move very slow close to the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(1.00f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 2000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 2000, 100); + DLOG(INFO) << "At available channel estimate"; + + // Send 50 bursts, make sure that we move very slow close to the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(1.01f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 2000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 2500, 100); + + // Send 50 bursts, make sure that we accelerate after the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(1.01f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 2000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 2900, 100); + + // Send 50 bursts, make sure that we accelerate after the probe rate. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(1.03f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 2000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 3400, 100); + + int64 max_rate = kMaxPacketSize * kNumMicrosPerSecond / + one_ms_.ToMicroseconds(); + + int64 halfway_rate = probe_rate + (max_rate - probe_rate) / 2; + + // Send until we reach halfway point. + for (int i = 0; i < 570; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(halfway_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 5000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 6600, 100); + DLOG(INFO) << "Near halfway point"; + + // Send until we reach max channel capacity. + for (int i = 0; i < 1500; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(max_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 5000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 10000, 200); +} + +TEST_F(InterArrivalSenderTest, DelaySpikeFollowedBySlowDrain) { + QuicCongestionFeedbackFrame feedback; + // At startup make sure we can send. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // Send 5 bursts. + for (int i = 0; i < 4; ++i) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + SendAvailableCongestionWindow(); + + // We have now sent our probe. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), NOT_RETRANSMISSION, + HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsInfinite()); + + AckNPackets(10); + SendFeedbackMessageNPackets(10, one_ms_, nine_ms_); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // We should now have our probe rate. + QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41); + int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond / + acc_arrival_time.ToMicroseconds(); + EXPECT_NEAR(0.7f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + + // Send 50 bursts, make sure that we move fast in the beginning. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.875f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 600, 10); + + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + + int64 rate_at_introduced_delay_spike = 0.875f * probe_rate; + QuicTime::Delta spike_time = QuicTime::Delta::FromMilliseconds(100); + SendDelaySpikeFeedbackMessage(spike_time); + + // Backing as much as we can, currently 90%. + EXPECT_NEAR(0.1f * rate_at_introduced_delay_spike, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 610, 10); + + // Run until we are catched up after our introduced delay spike. + while (send_clock_.Now() < receive_clock_.Now()) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, one_ms_); + } + // Expect that we go back to 67% of the rate before the spike. + EXPECT_NEAR(0.67f * rate_at_introduced_delay_spike, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 820, 10); + + // Send 100 bursts, make sure that we slow down towards the rate we had + // before the spike. + for (int i = 0; i < 100; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.97f * rate_at_introduced_delay_spike, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 2100, 10); +} + +TEST_F(InterArrivalSenderTest, DelaySpikeFollowedByImmediateDrain) { + QuicCongestionFeedbackFrame feedback; + // At startup make sure we can send. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // Send 5 bursts. + for (int i = 0; i < 4; ++i) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + SendAvailableCongestionWindow(); + + // We have now sent our probe. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), NOT_RETRANSMISSION, + HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsInfinite()); + + AckNPackets(10); + SendFeedbackMessageNPackets(10, one_ms_, nine_ms_); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // We should now have our probe rate. + QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41); + int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond / + acc_arrival_time.ToMicroseconds(); + EXPECT_NEAR(0.7f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + + // Send 50 bursts, make sure that we move fast in the beginning. + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, time_until_send.Subtract(one_ms_)); + } + EXPECT_NEAR(0.875f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 600, 10); + + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + AckNPackets(2); + + int64 rate_at_introduced_delay_spike = 0.875f * probe_rate; + QuicTime::Delta spike_time = QuicTime::Delta::FromMilliseconds(100); + SendDelaySpikeFeedbackMessage(spike_time); + + // Backing as much as we can, currently 90%. + EXPECT_NEAR(0.1f * rate_at_introduced_delay_spike, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 610, 10); + + // Move send time forward. + send_clock_.AdvanceTime(spike_time); + // Make sure our clocks are aligned again. + receive_clock_.AdvanceTime(send_clock_.Now().Subtract(receive_clock_.Now())); + + SendAvailableCongestionWindow(); + AckNPackets(2); + SendFeedbackMessageNPackets(2, one_ms_, one_ms_); + // We should now be back where we introduced the delay spike. + EXPECT_NEAR(rate_at_introduced_delay_spike, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 710, 10); +} + +TEST_F(InterArrivalSenderTest, MinBitrateDueToDelay) { + QuicBandwidth expected_min_bitrate = QuicBandwidth::FromKBitsPerSecond(10); + QuicCongestionFeedbackFrame feedback; + // At startup make sure we can send. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // Send 5 bursts. + for (int i = 0; i < 4; ++i) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + SendAvailableCongestionWindow(); + + AckNPackets(10); + + // One second spread per packet is expected to result in an estimate at + // our minimum bitrate. + SendFeedbackMessageNPackets(10, one_s_, one_s_); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + EXPECT_EQ(expected_min_bitrate, sender_.BandwidthEstimate()); +} + +TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) { + QuicBandwidth expected_min_bitrate = QuicBandwidth::FromKBitsPerSecond(10); + QuicCongestionFeedbackFrame feedback; + // At startup make sure we can send. + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + // Send 5 bursts. + for (int i = 0; i < 4; ++i) { + SendAvailableCongestionWindow(); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + } + SendAvailableCongestionWindow(); + + AckNPackets(10); + SendFeedbackMessageNPackets(10, nine_ms_, nine_ms_); + send_clock_.AdvanceTime(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE)); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + + QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(81); + int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond / + acc_arrival_time.ToMicroseconds(); + EXPECT_NEAR(0.7f * probe_rate, + sender_.BandwidthEstimate().ToBytesPerSecond(), 1000); + + for (int i = 0; i < 15; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + sender_.OnIncomingLoss(send_clock_.Now()); + sender_.OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_); + acked_sequence_number_ += 2; // Create a loss by not acking both packets. + SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_); + } + // Test that our exponentail back off stop at expected_min_bitrate. + EXPECT_EQ(expected_min_bitrate, sender_.BandwidthEstimate()); + + for (int i = 0; i < 50; ++i) { + SendAvailableCongestionWindow(); + QuicTime::Delta time_until_send = sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE); + send_clock_.AdvanceTime(time_until_send); + EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()); + sender_.OnIncomingLoss(send_clock_.Now()); + sender_.OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_); + acked_sequence_number_ += 2; // Create a loss by not acking both packets. + SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_); + + // Make sure our bitrate is fixed at the expected_min_bitrate. + EXPECT_EQ(expected_min_bitrate, sender_.BandwidthEstimate()); + } +} + +} // namespace test +} // namespace net |