1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "net/quic/congestion_control/tcp_cubic_sender.h"
10 #include "net/quic/congestion_control/tcp_receiver.h"
11 #include "net/quic/test_tools/mock_clock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
19 const uint32 kDefaultWindowTCP = 10 * kDefaultTCPMSS;
21 // TODO(ianswett): Remove 10000 once b/10075719 is fixed.
22 const QuicTcpCongestionWindow kDefaultMaxCongestionWindowTCP = 10000;
24 class TcpCubicSenderPeer : public TcpCubicSender {
26 TcpCubicSenderPeer(const QuicClock* clock,
28 QuicTcpCongestionWindow max_tcp_congestion_window)
29 : TcpCubicSender(clock, reno, max_tcp_congestion_window) {
32 QuicTcpCongestionWindow congestion_window() {
33 return congestion_window_;
36 using TcpCubicSender::AvailableSendWindow;
37 using TcpCubicSender::SendWindow;
40 class TcpCubicSenderTest : public ::testing::Test {
43 : one_ms_(QuicTime::Delta::FromMilliseconds(1)),
44 sender_(new TcpCubicSenderPeer(&clock_, true,
45 kDefaultMaxCongestionWindowTCP)),
46 receiver_(new TcpReceiver()),
48 acked_sequence_number_(0) {
51 int SendAvailableSendWindow() {
52 // Send as long as TimeUntilSend returns Zero.
54 bool can_send = sender_->TimeUntilSend(
55 clock_.Now(), NOT_RETRANSMISSION,
56 HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero();
58 sender_->OnPacketSent(clock_.Now(), sequence_number_++, kDefaultTCPMSS,
59 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
61 can_send = sender_->TimeUntilSend(
62 clock_.Now(), NOT_RETRANSMISSION,
63 HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero();
68 // Normal is that TCP acks every other segment.
69 void AckNPackets(int n) {
70 for (int i = 0; i < n; ++i) {
71 ++acked_sequence_number_;
72 sender_->UpdateRtt(QuicTime::Delta::FromMilliseconds(60));
73 sender_->OnPacketAcked(acked_sequence_number_, kDefaultTCPMSS);
75 clock_.AdvanceTime(one_ms_); // 1 millisecond.
78 void LoseNPackets(int n) {
79 for (int i = 0; i < n; ++i) {
80 ++acked_sequence_number_;
81 sender_->OnPacketAbandoned(acked_sequence_number_, kDefaultTCPMSS);
82 sender_->OnPacketLost(acked_sequence_number_, clock_.Now());
86 const QuicTime::Delta one_ms_;
88 SendAlgorithmInterface::SentPacketsMap not_used_;
89 scoped_ptr<TcpCubicSenderPeer> sender_;
90 scoped_ptr<TcpReceiver> receiver_;
91 QuicPacketSequenceNumber sequence_number_;
92 QuicPacketSequenceNumber acked_sequence_number_;
95 TEST_F(TcpCubicSenderTest, SimpleSender) {
96 QuicCongestionFeedbackFrame feedback;
97 // At startup make sure we are at the default.
98 EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
99 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
100 // At startup make sure we can send.
101 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
102 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
103 // Get default QuicCongestionFeedbackFrame from receiver.
104 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
105 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
107 // Make sure we can send.
108 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
109 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
110 // And that window is un-affected.
111 EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
112 EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
114 // A retransmit should always return 0.
115 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
116 NACK_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
119 TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
120 const int kNumberOfAcks = 20;
121 QuicCongestionFeedbackFrame feedback;
122 // At startup make sure we can send.
123 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
124 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
125 // Get default QuicCongestionFeedbackFrame from receiver.
126 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
127 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
129 // Make sure we can send.
130 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
131 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
133 for (int i = 0; i < kNumberOfAcks; ++i) {
134 // Send our full send window.
135 SendAvailableSendWindow();
138 QuicByteCount bytes_to_send = sender_->SendWindow();
139 EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAcks,
143 TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
144 // Make sure that we fall out of slow start when we send ACK train longer
145 // than half the RTT, in this test case 30ms, which is more than 30 calls to
146 // Ack2Packets in one round.
147 // Since we start at 10 packet first round will be 5 second round 10 etc
148 // Hence we should pass 30 at 65 = 5 + 10 + 20 + 30
149 const int kNumberOfAcks = 65;
150 QuicCongestionFeedbackFrame feedback;
151 // At startup make sure we can send.
152 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
153 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
154 // Get default QuicCongestionFeedbackFrame from receiver.
155 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
156 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
158 // Make sure we can send.
159 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
160 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
162 for (int i = 0; i < kNumberOfAcks; ++i) {
163 // Send our full send window.
164 SendAvailableSendWindow();
167 QuicByteCount expected_send_window =
168 kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAcks);
169 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
170 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
172 // We should now have fallen out of slow start.
173 // Testing Reno phase.
174 // We should need 141(65*2+1+10) ACK:ed packets before increasing window by
176 for (int i = 0; i < 70; ++i) {
177 SendAvailableSendWindow();
179 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
181 SendAvailableSendWindow();
183 expected_send_window += kDefaultTCPMSS;
184 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
187 TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
188 // Make sure that we fall out of slow start when we encounter a packet loss.
189 QuicCongestionFeedbackFrame feedback;
190 // At startup make sure we can send.
191 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
192 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
193 // Get default QuicCongestionFeedbackFrame from receiver.
194 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
195 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
197 // Make sure we can send.
198 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
199 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
201 const int kNumberOfAcks = 10;
202 for (int i = 0; i < kNumberOfAcks; ++i) {
203 // Send our full send window.
204 SendAvailableSendWindow();
207 SendAvailableSendWindow();
208 QuicByteCount expected_send_window = kDefaultWindowTCP +
209 (kDefaultTCPMSS * 2 * kNumberOfAcks);
210 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
212 sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
213 ++acked_sequence_number_;
215 // Make sure that we can send right now due to limited transmit.
216 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
217 HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
219 // We should now have fallen out of slow start.
220 // We expect window to be cut in half by Reno.
221 expected_send_window /= 2;
222 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
224 // Testing Reno phase.
225 // We need to ack half of the pending packet before we can send again.
226 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
227 AckNPackets(number_of_packets_in_window);
228 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
229 EXPECT_EQ(0u, sender_->AvailableSendWindow());
231 // We need to ack every packet in the window before we exit recovery.
232 for (size_t i = 0; i < number_of_packets_in_window; ++i) {
234 SendAvailableSendWindow();
235 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
238 // We need to ack another window before we increase CWND by 1.
239 for (size_t i = 0; i < number_of_packets_in_window - 1; ++i) {
241 SendAvailableSendWindow();
242 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
246 expected_send_window += kDefaultTCPMSS;
247 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
250 TEST_F(TcpCubicSenderTest, SlowStartPacketLossPRR) {
251 // Test based on the first example in RFC6937.
252 // Make sure that we fall out of slow start when we encounter a packet loss.
253 QuicCongestionFeedbackFrame feedback;
254 // At startup make sure we can send.
255 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
256 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
257 // Get default QuicCongestionFeedbackFrame from receiver.
258 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
259 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
262 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
263 const int kNumberOfAcks = 5;
264 for (int i = 0; i < kNumberOfAcks; ++i) {
265 // Send our full send window.
266 SendAvailableSendWindow();
269 SendAvailableSendWindow();
270 QuicByteCount expected_send_window = kDefaultWindowTCP +
271 (kDefaultTCPMSS * 2 * kNumberOfAcks);
272 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
276 // We should now have fallen out of slow start.
277 // We expect window to be cut in half by Reno.
278 expected_send_window /= 2;
279 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
281 // Send 1 packet to simulate limited transmit.
282 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
283 HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
284 EXPECT_EQ(1, SendAvailableSendWindow());
286 // Testing TCP proportional rate reduction.
287 // We should send one packet for every two received acks over the remaining
288 // 18 outstanding packets.
289 size_t number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
290 // The number of packets before we exit recovery is the original CWND minus
291 // the packet that has been lost and the one which triggered the loss.
292 size_t remaining_packets_in_recovery = number_of_packets_in_window * 2 - 1;
293 for (size_t i = 0; i < remaining_packets_in_recovery - 1; i += 2) {
295 EXPECT_TRUE(sender_->TimeUntilSend(
296 clock_.Now(), NOT_RETRANSMISSION,
297 HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
298 EXPECT_EQ(0u, sender_->AvailableSendWindow());
299 EXPECT_EQ(1, SendAvailableSendWindow());
300 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
302 // If there is one more packet to ack before completing recovery, ack it.
303 if (remaining_packets_in_recovery % 2 == 1) {
307 // We need to ack another window before we increase CWND by 1.
308 for (size_t i = 0; i < number_of_packets_in_window; ++i) {
310 EXPECT_EQ(1, SendAvailableSendWindow());
311 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
315 expected_send_window += kDefaultTCPMSS;
316 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
319 TEST_F(TcpCubicSenderTest, SlowStartBurstPacketLossPRR) {
320 // Test based on the second example in RFC6937, though we also implement
321 // forward acknowledgements, so the first two incoming acks will trigger
323 // Make sure that we fall out of slow start when we encounter a packet loss.
324 QuicCongestionFeedbackFrame feedback;
325 // At startup make sure we can send.
326 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
327 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
328 // Get default QuicCongestionFeedbackFrame from receiver.
329 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
330 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
333 // Ack 10 packets in 5 acks to raise the CWND to 20, as in the example.
334 const int kNumberOfAcks = 5;
335 for (int i = 0; i < kNumberOfAcks; ++i) {
336 // Send our full send window.
337 SendAvailableSendWindow();
340 SendAvailableSendWindow();
341 QuicByteCount expected_send_window = kDefaultWindowTCP +
342 (kDefaultTCPMSS * 2 * kNumberOfAcks);
343 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
345 // Ack a packet with a 15 packet gap, losing 13 of them due to FACK.
346 sender_->OnPacketAcked(acked_sequence_number_ + 15, kDefaultTCPMSS);
349 // We should now have fallen out of slow start.
350 // We expect window to be cut in half by Reno.
351 expected_send_window /= 2;
352 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
354 // Only 2 packets should be allowed to be sent, per PRR-SSRB
355 EXPECT_EQ(2, SendAvailableSendWindow());
357 // Ack the next packet, which triggers another loss.
358 sender_->OnPacketAcked(acked_sequence_number_ + 4, kDefaultTCPMSS);
361 // Send 2 packets to simulate PRR-SSRB.
362 EXPECT_EQ(2, SendAvailableSendWindow());
364 // Ack the next packet, which triggers another loss.
365 sender_->OnPacketAcked(acked_sequence_number_ + 4, kDefaultTCPMSS);
368 // Send 2 packets to simulate PRR-SSRB.
369 EXPECT_EQ(2, SendAvailableSendWindow());
372 EXPECT_EQ(2, SendAvailableSendWindow());
375 EXPECT_EQ(2, SendAvailableSendWindow());
377 // The window should not have changed.
378 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
380 // Exit recovery and return to sending at the new rate.
381 for (int i = 0; i < kNumberOfAcks; ++i) {
383 EXPECT_EQ(1, SendAvailableSendWindow());
387 TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
388 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow());
390 // Expect the window to decrease to the minimum once the RTO fires.
391 sender_->OnRetransmissionTimeout(true);
392 EXPECT_EQ(2 * kDefaultTCPMSS, sender_->SendWindow());
395 TEST_F(TcpCubicSenderTest, RTOCongestionWindowNoRetransmission) {
396 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow());
398 // Expect the window to remain unchanged if the RTO fires but no
399 // packets are retransmitted.
400 sender_->OnRetransmissionTimeout(false);
401 EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow());
404 TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
405 const int64 kRttMs = 10;
406 const int64 kDeviationMs = 3;
407 EXPECT_EQ(QuicTime::Delta::Zero(), sender_->RetransmissionDelay());
409 sender_->UpdateRtt(QuicTime::Delta::FromMilliseconds(kRttMs));
411 // Initial value is to set the median deviation to half of the initial
412 // rtt, the median in then multiplied by a factor of 4 and finally the
413 // smoothed rtt is added which is the initial rtt.
414 QuicTime::Delta expected_delay =
415 QuicTime::Delta::FromMilliseconds(kRttMs + kRttMs / 2 * 4);
416 EXPECT_EQ(expected_delay, sender_->RetransmissionDelay());
418 for (int i = 0; i < 100; ++i) {
419 // Run to make sure that we converge.
421 QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs));
423 QuicTime::Delta::FromMilliseconds(kRttMs - kDeviationMs));
425 expected_delay = QuicTime::Delta::FromMilliseconds(kRttMs + kDeviationMs * 4);
427 EXPECT_NEAR(kRttMs, sender_->SmoothedRtt().ToMilliseconds(), 1);
428 EXPECT_NEAR(expected_delay.ToMilliseconds(),
429 sender_->RetransmissionDelay().ToMilliseconds(),
431 EXPECT_EQ(static_cast<int64>(
432 sender_->GetCongestionWindow() * kNumMicrosPerSecond /
433 sender_->SmoothedRtt().ToMicroseconds()),
434 sender_->BandwidthEstimate().ToBytesPerSecond());
437 TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
438 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
439 const int kNumberOfAcks = 100;
441 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
443 QuicCongestionFeedbackFrame feedback;
444 // At startup make sure we can send.
445 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
446 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
447 // Get default QuicCongestionFeedbackFrame from receiver.
448 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
449 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
451 // Make sure we can send.
452 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
453 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
455 for (int i = 0; i < kNumberOfAcks; ++i) {
456 // Send our full send window.
457 SendAvailableSendWindow();
460 QuicByteCount expected_send_window =
461 kMaxCongestionWindowTCP * kDefaultTCPMSS;
462 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
465 TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
466 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
467 const int kNumberOfAcks = 1000;
469 new TcpCubicSenderPeer(&clock_, true, kMaxCongestionWindowTCP));
471 QuicCongestionFeedbackFrame feedback;
472 // At startup make sure we can send.
473 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
474 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
475 // Get default QuicCongestionFeedbackFrame from receiver.
476 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
477 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
479 // Make sure we can send.
480 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
481 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
483 SendAvailableSendWindow();
485 // Make sure we fall out of slow start.
486 sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
488 for (int i = 0; i < kNumberOfAcks; ++i) {
489 // Send our full send window.
490 SendAvailableSendWindow();
494 QuicByteCount expected_send_window =
495 kMaxCongestionWindowTCP * kDefaultTCPMSS;
496 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
499 TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
500 const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
501 // Set to 10000 to compensate for small cubic alpha.
502 const int kNumberOfAcks = 10000;
505 new TcpCubicSenderPeer(&clock_, false, kMaxCongestionWindowTCP));
507 QuicCongestionFeedbackFrame feedback;
508 // At startup make sure we can send.
509 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
510 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
511 // Get default QuicCongestionFeedbackFrame from receiver.
512 ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
513 sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
515 // Make sure we can send.
516 EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
517 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
519 SendAvailableSendWindow();
521 // Make sure we fall out of slow start.
522 sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
524 for (int i = 0; i < kNumberOfAcks; ++i) {
525 // Send our full send window.
526 SendAvailableSendWindow();
530 QuicByteCount expected_send_window =
531 kMaxCongestionWindowTCP * kDefaultTCPMSS;
532 EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
535 TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
536 SendAvailableSendWindow();
537 const QuicByteCount initial_window = sender_->GetCongestionWindow();
538 sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
539 const QuicByteCount post_loss_window = sender_->GetCongestionWindow();
540 EXPECT_GT(initial_window, post_loss_window);
541 sender_->OnPacketLost(acked_sequence_number_ + 3, clock_.Now());
542 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
543 sender_->OnPacketLost(sequence_number_ - 1, clock_.Now());
544 EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
546 // Lose a later packet and ensure the window decreases.
547 sender_->OnPacketLost(sequence_number_, clock_.Now());
548 EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
551 TEST_F(TcpCubicSenderTest, SendWindowNotAffectedByAcks) {
552 QuicByteCount send_window = sender_->AvailableSendWindow();
554 // Send a packet with no retransmittable data, and ensure that the congestion
555 // window doesn't change.
556 QuicByteCount bytes_in_packet = min(kDefaultTCPMSS, send_window);
557 sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
558 NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
559 EXPECT_EQ(send_window, sender_->AvailableSendWindow());
561 // Send a data packet with retransmittable data, and ensure that the
562 // congestion window has shrunk.
563 sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
564 NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
565 EXPECT_GT(send_window, sender_->AvailableSendWindow());
568 TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) {
569 QuicTcpCongestionWindow congestion_window = sender_->congestion_window();
571 config.set_server_initial_congestion_window(2 * congestion_window,
572 2 * congestion_window);
573 EXPECT_EQ(2 * congestion_window, config.server_initial_congestion_window());
575 sender_->SetFromConfig(config, true);
576 EXPECT_EQ(2 * congestion_window, sender_->congestion_window());