tcp_cubic_sender_test.cc revision 558790d6acca3451cf3a6b497803a5f07d0bec58
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/congestion_control/tcp_cubic_sender.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/congestion_control/tcp_receiver.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/test_tools/mock_clock.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test {
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint32 kDefaultWindowTCP = 10 * kMaxPacketSize;
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const QuicByteCount kNoNBytesInFlight = 0;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TcpCubicSenderPeer : public TcpCubicSender {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
20558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  TcpCubicSenderPeer(const QuicClock* clock, bool reno)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : TcpCubicSender(clock, reno) {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using TcpCubicSender::AvailableCongestionWindow;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  using TcpCubicSender::CongestionWindow;
25558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  using TcpCubicSender::AckAccounting;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TcpCubicSenderTest : public ::testing::Test {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TcpCubicSenderTest()
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     : rtt_(QuicTime::Delta::FromMilliseconds(60)),
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       one_ms_(QuicTime::Delta::FromMilliseconds(1)),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       sender_(new TcpCubicSenderPeer(&clock_, true)),
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       receiver_(new TcpReceiver()),
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       sequence_number_(1),
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       acked_sequence_number_(0) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SendAvailableCongestionWindow() {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    QuicByteCount bytes_to_send = sender_->AvailableCongestionWindow();
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    while (bytes_to_send > 0) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      QuicByteCount bytes_in_packet = std::min(kMaxPacketSize, bytes_to_send);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sender_->SentPacket(clock_.Now(), sequence_number_++, bytes_in_packet,
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          NOT_RETRANSMISSION);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_to_send -= bytes_in_packet;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (bytes_to_send > 0) {
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                           HAS_RETRANSMITTABLE_DATA).IsZero());
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Normal is that TCP acks every other segment.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AckNPackets(int n) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < n; ++i) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      acked_sequence_number_++;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sender_->OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_);
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    clock_.AdvanceTime(one_ms_);  // 1 millisecond.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const QuicTime::Delta rtt_;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const QuicTime::Delta one_ms_;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MockClock clock_;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAlgorithmInterface::SentPacketsMap not_used_;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TcpCubicSenderPeer> sender_;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TcpReceiver> receiver_;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicPacketSequenceNumber sequence_number_;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicPacketSequenceNumber acked_sequence_number_;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(TcpCubicSenderTest, SimpleSender) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicCongestionFeedbackFrame feedback;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At startup make sure we are at the default.
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kDefaultWindowTCP,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            sender_->AvailableCongestionWindow());
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At startup make sure we can send.
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get default QuicCongestionFeedbackFrame from receiver.
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 not_used_);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we can send.
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // And that window is un-affected.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableCongestionWindow());
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // A retransmitt should always retun 0.
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), IS_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumberOfAck = 20;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicCongestionFeedbackFrame feedback;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At startup make sure we can send.
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get default QuicCongestionFeedbackFrame from receiver.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 not_used_);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we can send.
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int n = 0; n < kNumberOfAck; ++n) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send our full congestion window.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAvailableCongestionWindow();
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AckNPackets(2);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicByteCount bytes_to_send = sender_->CongestionWindow();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kDefaultWindowTCP + kMaxPacketSize * 2 * kNumberOfAck,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            bytes_to_send);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that we fall out of slow start when we send ACK train longer
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than half the RTT, in this test case 30ms, which is more than 30 calls to
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ack2Packets in one round.
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since we start at 10 packet first round will be 5 second round 10 etc
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumberOfAck = 65;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicCongestionFeedbackFrame feedback;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At startup make sure we can send.
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get default QuicCongestionFeedbackFrame from receiver.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 not_used_);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we can send.
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int n = 0; n < kNumberOfAck; ++n) {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send our full congestion window.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAvailableCongestionWindow();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AckNPackets(2);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicByteCount expected_congestion_window = kDefaultWindowTCP +
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (kMaxPacketSize * 2 * kNumberOfAck);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should now have fallen out of slow start.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAvailableCongestionWindow();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckNPackets(2);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_congestion_window += kMaxPacketSize;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Testing Reno phase.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should need 141(65*2+1+10) ACK:ed packets before increasing window by
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // one.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int m = 0; m < 70; ++m) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAvailableCongestionWindow();
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AckNPackets(2);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAvailableCongestionWindow();
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckNPackets(2);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_congestion_window += kMaxPacketSize;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that we fall out of slow start when we encounter a packet loss.
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kNumberOfAck = 10;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicCongestionFeedbackFrame feedback;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // At startup make sure we can send.
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get default QuicCongestionFeedbackFrame from receiver.
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                 not_used_);
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we can send.
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < kNumberOfAck; ++i) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send our full congestion window.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAvailableCongestionWindow();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AckNPackets(2);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAvailableCongestionWindow();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  QuicByteCount expected_congestion_window = kDefaultWindowTCP +
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (kMaxPacketSize * 2 * kNumberOfAck);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sender_->OnIncomingLoss(clock_.Now());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure that we should not send right now.
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(sender_->TimeUntilSend(
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsInfinite());
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should now have fallen out of slow start.
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We expect window to be cut in half.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_congestion_window /= 2;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Testing Reno phase.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to ack half of the pending packet before we can send agin.
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int number_of_packets_in_window = expected_congestion_window / kMaxPacketSize;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckNPackets(number_of_packets_in_window);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0u, sender_->AvailableCongestionWindow());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckNPackets(1);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_congestion_window += kMaxPacketSize;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  number_of_packets_in_window++;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We should need number_of_packets_in_window ACK:ed packets before
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // increasing window by one.
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int k = 0; k < number_of_packets_in_window; ++k) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAvailableCongestionWindow();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AckNPackets(1);
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAvailableCongestionWindow();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AckNPackets(1);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected_congestion_window += kMaxPacketSize;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
225558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(TcpCubicSenderTest, RetransmissionDelay) {
226558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const int64 kRttMs = 10;
227558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  const int64 kDeviationMs = 3;
228558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
229558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
230558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  sender_->AckAccounting(QuicTime::Delta::FromMilliseconds(kRttMs));
231558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
232558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Initial value is to set the median deviation to half of the initial
233558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // rtt, the median in then multiplied by a factor of 4 and finaly the
234558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // smoothed rtt is added which is the inital rtt.
235558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  QuicTime::Delta expected_delay =
236558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
237558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
238558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
239558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  for (int i = 0; i < 100; ++i) {
240558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    // Run to make sure that we converge.
241558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    sender_->AckAccounting(
242558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs));
243558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    sender_->AckAccounting(
244558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch        QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs));
245558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
246558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
247558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
248558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  EXPECT_NEAR(kRttMs, sender_->SmoothedRtt().ToMilliseconds(), 1);
249558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  EXPECT_NEAR(expected_delay.ToMilliseconds(),
250558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch              sender_->RetransmissionDelay().ToMilliseconds(),
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch              1);
252558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace test
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
255